Backporting Fixes from S12 --> S11.2 s11-update s11u2b22
authorsaurabh.vyas@oracle.com
Wed, 14 Aug 2013 11:12:35 +0530
branchs11-update
changeset 2938 1d287dc7a674
parent 2917 329157d9103e (current diff)
parent 2928 71a6862183d8 (diff)
child 2939 09250dfe46f3
Backporting Fixes from S12 --> S11.2
.hgtags
src/checkforupdates.py
src/man/packagemanager.1
src/man/pkg.1
src/man/pkg.5
src/man/pkg.depot-config.1m
src/man/pkg.depotd.1m
src/man/pkg.sysrepo.1m
src/man/pkgdepend.1
src/man/pkgdiff.1
src/man/pkgfmt.1
src/man/pkglint.1
src/man/pkgmerge.1
src/man/pkgmogrify.1
src/man/pkgrecv.1
src/man/pkgrepo.1
src/man/pkgsend.1
src/man/pkgsign.1
src/man/pkgsurf.1
src/man/pm-updatemanager.1
src/modules/actions/__init__.py
src/modules/altroot.py
src/modules/client/api.py
src/modules/client/pkg_solver.py
src/modules/client/progress.py
src/modules/client/transport/repo.py
src/modules/file_layout/file_manager.py
src/modules/gui/installupdate.py
src/modules/manifest.py
src/modules/misc.py
src/modules/server/repository.py
src/packagemanager.py
src/pkg/Makefile
src/pkg/manifests/SUNWipkg-gui-data.p5m
src/pkg/manifests/SUNWipkg-gui-l10n.p5m
src/pkg/manifests/package:pkg.p5m
src/pkgrepo.py
src/setup.py
src/tests/cli/t_change_facet.py
src/tests/cli/t_https.py
src/tests/cli/t_pkg_install.py
src/tests/cli/t_pkg_sysrepo.py
src/tests/cli/t_pkgrepo.py
src/tests/cli/t_sysrepo.py
src/tests/pkg5unittest.py
src/um/pkg-update
src/util/apache2/sysrepo/sysrepo_httpd.conf.mako
--- a/.hgignore	Thu Jul 18 09:40:49 2013 -0700
+++ b/.hgignore	Wed Aug 14 11:12:35 2013 +0530
@@ -34,11 +34,13 @@
 ^src/gui/help/package-manager-__LOCALE__.omf$
 ^src/pkg/Makefile.link
 ^src/pkg/pkgtmp/
+^src/po/i18n_errs.txt$
 ^src/po/pkg.pot$
 ^src/tests/.coverage$
 ^src/tests/.coverage-.*$
+^src/tests/cov_proto.*$
+^src/tests/cov_tests.*$
 ^src/tests/.timing_history.txt$
-^src/tests/htmlcov$
 ^src/tests/ro_data/signing_certs/produced/.*/.*\.csr
 ^src/tests/ro_data/signing_certs/produced/.*\.old
 ^src/tests/ro_data/signing_certs/produced/.*\.tmp
--- a/doc/client_api_versions.txt	Thu Jul 18 09:40:49 2013 -0700
+++ b/doc/client_api_versions.txt	Wed Aug 14 11:12:35 2013 +0530
@@ -1,5 +1,41 @@
+Version 76:
+Compatible with clients using versions 72-75 [1].
+
+    pkg.client.api.ImageInterface has changed as follows:
+
+	* The generator functions 'gen_facets()' has been updated to
+	  give more information about what facets are changing.
+	  Previously a 2 value tuple was returned, now a 4 value tuple
+	  is returned.
+
+	* [1] This is actually an incompatible change to the old
+	  'gen_facets()' behavior, but since gen_facets was only
+	  introduced in the previous version of the client API it's
+	  unlikely that anyone outside of the pkg gate has adopted it's
+	  use.  But since we'd like to avoid an incompatible client API
+	  change we're going to ignore this issue.
+
+	* The parsable package plan output format for facet changes has
+	  been changed.  Previously a tuple with 2 values was returned;
+	  now a tuple with 6 values is returned.
+
+	* Added 'li_parent_sync' parameter to 'gen_plan_uninstall()'.
+
+	* Added 'li_md_only' and 'li_pkg_updates' parameters to
+	  'gen_plan_detach()' and 'detach_linked_children()'
+
+Version 75:
+Compatible with clients using versions 72-74.
+
+    pkg.client.api.ImageInterface has changed as follows:
+
+	* New generator functions 'gen_variants()' and 'gen_facets()' to
+	  retrieve the current list of facets or variants currently
+	  (implicitly or explicitly) set in the image.  See 'pydoc
+	  pkg.client.api' for details.
+
 Version 74:
-Compatible with clients using version 73, 72.
+Compatible with clients using versions 72-74.
      The PlanDescription now has interfaces to
      determine whether or not release notes were generated
      for this operation, whether or not they must be displayed,
--- a/doc/guide-naming-conventions.rst	Thu Jul 18 09:40:49 2013 -0700
+++ b/doc/guide-naming-conventions.rst	Wed Aug 14 11:12:35 2013 +0530
@@ -31,14 +31,14 @@
 fault management architecture, each package is named by an FMRI in the
 ``pkg:`` scheme.  That is, we have::
 
-    pkg://authority/pkg_name@version
+    pkg://publisher/pkg_name@version
 
-The authority is generally expected to be a forward or reverse domain
+The publisher is generally expected to be a forward or reverse domain
 name identifying the publisher from which a package can be retrieved.
-Authorities which cannot be determined to be a domain name are
+Publishers which cannot be determined to be a domain name are
 legitimate, but optional functionality, like automatic server discovery
-for a particular authority, may fail to work.  In the examples that
-follow, we use "opensolaris.org" as a generic authority.
+for a particular publisher, may fail to work.  In the examples that
+follow, we use "opensolaris.org" as a generic publisher.
 
 Although RFC 2396 usage would suggest using the "authority" term, we
 instead call it the publisher name, as the role of this section of the
@@ -62,7 +62,7 @@
 Namespace
 ~~~~~~~~~
 
-Single namespace, separate authorities
+Single namespace, separate publishers
 ``````````````````````````````````````
 
 The primary design point of the package namespace is to allow
--- a/doc/pkgs-and-groups.txt	Thu Jul 18 09:40:49 2013 -0700
+++ b/doc/pkgs-and-groups.txt	Wed Aug 14 11:12:35 2013 +0530
@@ -10,15 +10,15 @@
     fault management architecture, each package is named by an FMRI in
     the "pkg:" scheme.  That is, we have
 
-    pkg://authority/pkg_name@version
+    pkg://publisher/pkg_name@version
 
-    The authority is generally expected to be a forward or reverse
+    The publisher is generally expected to be a forward or reverse
     domain name identifying the publisher from which a package can be
-    retrieved.  Authorities which cannot be determined to be a domain
+    retrieved.  Publishers which cannot be determined to be a domain
     name are legitimate, but optional functionality, like automatic
-    server discovery for a particular authority, may fail to work.
+    server discovery for a particular publisher, may fail to work.
     In the examples that follow, we use "opensolaris.org" as a generic
-    authority.
+    publisher.
 
     The pkg_name, like service names, can be split into a category,
     subcategories, and a basename.  This namespace might be populated
@@ -35,7 +35,7 @@
 
 2.  Namespace
 
-2.1.  Single namespace, separate authorities
+2.1.  Single namespace, separate publishers
 
     The primary design point of the package namespace is to allow
     multiple package producers to co-exist in a single namespace, so
--- a/exception_lists/keywords	Thu Jul 18 09:40:49 2013 -0700
+++ b/exception_lists/keywords	Wed Aug 14 11:12:35 2013 +0530
@@ -20,9 +20,9 @@
 #
 
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
+src/modules/client/api.py
 src/modules/client/image.py
 src/client.py
--- a/src/checkforupdates.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/checkforupdates.py	Wed Aug 14 11:12:35 2013 +0530
@@ -37,6 +37,7 @@
 import traceback
 import warnings
 
+import pkg.client.api as api
 import pkg.client.api_errors as apx
 import pkg.client.progress as progress
 import pkg.client.printengine as printengine
@@ -63,8 +64,14 @@
                 global_settings.client_name = nongui_misc.get_um_name()
                 self.api_lock = nrlock.NRLock()
                 self.image_dir_arg = image_directory
+                self.exact_match = True
                 if self.image_dir_arg == None:
-                        self.image_dir_arg = nongui_misc.get_image_path()
+                        self.image_dir_arg, self.exact_match =  \
+                            api.get_default_image_root()
+                if not self.exact_match:
+                        logger.debug("Unable to get image directory")
+                        sys.exit(enumerations.UPDATES_UNDETERMINED)
+                        
                 self.application_path = application_path
                 self.check_all = check_all
                 self.check_cache_only = check_cache
@@ -264,7 +271,7 @@
         """Main routine for this utility"""
         set_check_all = True
         set_check_cache = False
-        image_dir = "/"
+        image_dir = None 
         try:
                 # Unused variable pargs; pylint: disable=W0612
                 opts, pargs = getopt.getopt(sys.argv[1:], "hdnacR:",
--- a/src/client.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/client.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 #
@@ -62,7 +62,6 @@
         import textwrap
         import time
         import traceback
-        import tempfile
 
         import pkg
         import pkg.actions as actions
@@ -72,6 +71,7 @@
         import pkg.client.progress as progress
         import pkg.client.linkedimage as li
         import pkg.client.publisher as publisher
+        import pkg.client.options as options
         import pkg.fmri as fmri
         import pkg.misc as misc
         import pkg.pipeutils as pipeutils
@@ -91,7 +91,7 @@
         import sys
         sys.exit(1)
 
-CLIENT_API_VERSION = 74
+CLIENT_API_VERSION = 75
 PKG_CLIENT_NAME = "pkg"
 
 JUST_UNKNOWN = 0
@@ -171,7 +171,7 @@
             "            [--deny-new-be | --require-new-be] [--be-name name]\n"
             "            [--reject pkg_fmri_pattern ...] [pkg_fmri_pattern ...]")
         basic_usage["list"] = _(
-            "[-Hafnsuv] [-g path_or_uri ...] [--no-refresh]\n"
+            "[-Hafnqsuv] [-g path_or_uri ...] [--no-refresh]\n"
             "            [pkg_fmri_pattern ...]")
         basic_usage["refresh"] = _("[-q] [--full] [publisher ...]")
         basic_usage["version"] = ""
@@ -220,7 +220,7 @@
         ]
 
         adv_usage["info"] = \
-            _("[-lr] [-g path_or_uri ...] [--license] [pkg_fmri_pattern ...]")
+            _("[-lqr] [-g path_or_uri ...] [--license] [pkg_fmri_pattern ...]")
         adv_usage["contents"] = _(
             "[-Hmr] [-a attribute=pattern ...] [-g path_or_uri ...]\n"
             "            [-o attribute ...] [-s sort_key] [-t action_type ...]\n"
@@ -271,8 +271,8 @@
             "            [--deny-new-be | --require-new-be] [--be-name name]\n"
             "            <mediator> ...")
 
-        adv_usage["variant"] = _("[-H] [<variant_spec>]")
-        adv_usage["facet"] = ("[-H] [<facet_spec>]")
+        adv_usage["variant"] = _("[-Haiv] [-F format] [<variant_pattern> ...]")
+        adv_usage["facet"] = ("[-Haim] [-F format] [<facet_pattern> ...]")
         adv_usage["avoid"] = _("[pkg_fmri_pattern] ...")
         adv_usage["unavoid"] = _("[pkg_fmri_pattern] ...")
         adv_usage["freeze"] = _("[-n] [-c reason] [pkg_fmri_pattern] ...")
@@ -320,9 +320,10 @@
             "            [--prop-linked <propname>=<propvalue> ...]\n"
             "            (-c|-p) <li-name> <dir>")
         priv_usage["detach-linked"] = _(
-            "[-fnvq] [-a|-l <li-name>] [--linked-md-only]")
+            "[-fnvq] [-a|-l <li-name>] [--no-pkg-updates] [--linked-md-only]")
         priv_usage["property-linked"] = _("[-H] [-l <li-name>] [propname ...]")
-        priv_usage["audit-linked"] = _("[-a|-l <li-name>]")
+        priv_usage["audit-linked"] = _(
+            "[-H] [-a|-l <li-name>] [--no-parent-sync]")
         priv_usage["pubcheck-linked"] = ""
         priv_usage["sync-linked"] = _(
             "[-nvq] [-C n] [--accept] [--licenses] [--no-index]\n"
@@ -345,10 +346,10 @@
                                         raise ValueError(
                                             "Unable to find usage str for %s" %
                                             cmd)
-                                usage = cmd_dic[cmd]
-                                if usage is not "":
+                                use_txt = cmd_dic[cmd]
+                                if use_txt is not "":
                                         logger.error(
-                                            "        pkg %(cmd)s %(usage)s" %
+                                            "        pkg %(cmd)s %(use_txt)s" %
                                             locals())
                                 else:
                                         logger.error("        pkg %s" % cmd)
@@ -413,7 +414,7 @@
 
 def list_inventory(op, api_inst, pargs,
     li_parent_sync, list_all, list_installed_newest, list_newest,
-    list_upgradable, omit_headers, origins, refresh_catalogs, summary,
+    list_upgradable, omit_headers, origins, quiet, refresh_catalogs, summary,
     verbose):
         """List packages."""
 
@@ -495,6 +496,10 @@
                     raise_unmatched=True, repos=origins, variants=variants)
                 for pt, summ, cats, states, attrs in res:
                         found = True
+
+                        if quiet:
+                                continue
+
                         if not omit_headers:
                                 if verbose:
                                         msg(fmt_str %
@@ -545,24 +550,29 @@
 
                 if not found and not pargs:
                         if pkg_list == api_inst.LIST_INSTALLED:
-                                error(_("no packages installed"))
+                                if not quiet:
+                                        error(_("no packages installed"))
                                 api_inst.log_operation_end(
                                     result=RESULT_NOTHING_TO_DO)
                                 return EXIT_OOPS
                         elif pkg_list == api_inst.LIST_INSTALLED_NEWEST:
-                                error(_("no packages installed or available "
-                                    "for installation"))
+                                if not quiet:
+                                        error(_("no packages installed or available "
+                                            "for installation"))
                                 api_inst.log_operation_end(
                                     result=RESULT_NOTHING_TO_DO)
                                 return EXIT_OOPS
                         elif pkg_list == api_inst.LIST_UPGRADABLE:
-                                img = api_inst._img
-                                cat = img.get_catalog(img.IMG_CATALOG_INSTALLED)
-                                if cat.package_count > 0:
-                                        error(_("no packages have newer "
-                                            "versions available"))
-                                else:
-                                        error(_("no packages are installed"))
+                                if not quiet:
+                                        img = api_inst._img
+                                        cat = img.get_catalog(
+                                            img.IMG_CATALOG_INSTALLED)
+                                        if cat.package_count > 0:
+                                                error(_("no packages have "
+                                                    "newer versions available"))
+                                        else:
+                                                error(_("no packages are "
+                                                    "installed"))
                                 api_inst.log_operation_end(
                                     result=RESULT_NOTHING_TO_DO)
                                 return EXIT_OOPS
@@ -578,6 +588,9 @@
             api_errors.PermissionsException), e:
                 error(e, cmd=op)
                 return EXIT_OOPS
+        except api_errors.CatalogRefreshException, e:
+                display_catalog_failures(e)
+                return EXIT_OOPS
         except api_errors.InventoryException, e:
                 if e.illegal:
                         for i in e.illegal:
@@ -586,12 +599,15 @@
                             result=RESULT_FAILED_BAD_REQUEST)
                         return EXIT_OOPS
 
-                if found:
+                if found and not quiet:
                         # Ensure a blank line is inserted after list for
                         # partial failure case.
                         logger.error(" ")
 
-                if pkg_list == api.ImageInterface.LIST_ALL or \
+                if quiet:
+                        # Print nothing.
+                        pass
+                elif pkg_list == api.ImageInterface.LIST_ALL or \
                     pkg_list == api.ImageInterface.LIST_NEWEST:
                         error(_("no packages matching '%s' known") % \
                             ", ".join(e.notfound), cmd=op)
@@ -602,12 +618,39 @@
                             ", ".join(e.notfound), cmd=op)
                         logger.error("Use -af to allow all versions.")
                 elif pkg_list == api.ImageInterface.LIST_UPGRADABLE:
-                        error(_("no packages matching '%s' are installed "
-                            "and have newer versions available") % \
-                            ", ".join(e.notfound), cmd=op)
-                else:
-                        error(_("no packages matching '%s' installed") % \
-                            ", ".join(e.notfound), cmd=op)
+			# Creating a list of packages that are uptodate
+			# and that are not installed on the system.
+                        no_updates = []
+                        not_installed = []
+                        try:
+                                for entry in api_inst.get_pkg_list(
+				    api.ImageInterface.LIST_INSTALLED,
+                                    patterns=e.notfound, raise_unmatched=True):
+                                        pub, stem, ver = entry[0]
+                                        no_updates.append(stem)
+                        except api_errors.InventoryException, exc:
+                                not_installed = exc.notfound
+
+			err_str = ""
+                        if len(not_installed) == 1:
+				err_str = _("No package matching '%s'"
+					  " is installed. ") % \
+					  not_installed[0]
+                        elif not_installed:
+                                err_str = _("No packages matching '%s'"
+                                    " are installed. ") % \
+                                    ", ".join(not_installed)
+
+                        if len(no_updates) == 1:
+                                err_str = err_str + _("No updates are available"
+                                          " for package '%s'.") % \
+                                            no_updates[0]
+                        elif no_updates:
+                                err_str = err_str + _("No updates are available"
+                                          " for packages '%s'.") % \
+                                            ", ".join(no_updates)
+			if err_str:
+                                error(err_str, cmd=op) 
 
                 if found and e.notfound:
                         # Only some patterns matched.
@@ -622,16 +665,16 @@
         elif global_settings.client_output_quiet:
                 progresstracker = progress.QuietProgressTracker()
         elif global_settings.client_output_progfd:
-		# This logic handles linked images: for linked children
-		# we elide the progress output.
+                # This logic handles linked images: for linked children
+                # we elide the progress output.
                 output_file = os.fdopen(global_settings.client_output_progfd,
-		    "w")
+                    "w")
                 child_tracker = progress.LinkedChildProgressTracker(
                     output_file=output_file)
-		dot_tracker = progress.DotProgressTracker(
-		    output_file=output_file)
-		progresstracker = progress.MultiProgressTracker(
-		    [child_tracker, dot_tracker])
+                dot_tracker = progress.DotProgressTracker(
+                    output_file=output_file)
+                progresstracker = progress.MultiProgressTracker(
+                    [child_tracker, dot_tracker])
         else:
                 try:
                         progresstracker = progress.FancyUNIXProgressTracker()
@@ -807,12 +850,17 @@
                 elif opt == "-q":
                         quiet = True
                         display_headers = False
+                        global_settings.client_output_quiet = True
 
         if verbose and quiet:
                 usage(_("-v and -q may not be combined"), cmd="verify")
         if verbose > 2:
                 DebugValues.set_value("plan", "True")
 
+        # Reset the progress tracker here, because we may have
+        # to switch to a different tracker due to the options parse.
+        _api_inst.progresstracker = get_tracker()
+
         # XXX verify should be part of pkg.client.api
         any_errors = False
         processed = False
@@ -975,7 +1023,9 @@
                 elif src != dest:
                         c.append((src, dest))
                 else:
-                        a.append((src, dest))
+                        # Changing or repairing package content (e.g. fix,
+                        # change-facet, etc.)
+                        a.append((dest, dest))
 
         def bool_str(val):
                 if val:
@@ -993,8 +1043,15 @@
                 cond_show(_("Packages to remove:"), "%d", len(r))
                 cond_show(_("Packages to install:"), "%d", len(i))
                 cond_show(_("Packages to update:"), "%d", len(c))
+                if varcets or mediators:
+                        cond_show(_("Packages to change:"), "%d", len(a))
+                else:
+                        cond_show(_("Packages to fix:"), "%d", len(a))
                 cond_show(_("Mediators to change:"), "%d", len(mediators))
                 cond_show(_("Variants/Facets to change:"), "%d", len(varcets))
+                if not plan.new_be:
+                        cond_show(_("Services to change:"), "%d",
+                            len(plan.services))
 
                 if verbose:
                         # Only show space information in verbose mode.
@@ -1006,11 +1063,6 @@
                                     _("Estimated space to be consumed:"),
                                     misc.bytes_to_str(plan.bytes_added)))
 
-                if varcets or mediators:
-                        cond_show(_("Packages to change:"), "%d", len(a))
-                else:
-                        cond_show(_("Packages to fix:"), "%d", len(a))
-
                 # only display BE information if we're operating on the
                 # liveroot environment (since otherwise we'll never be
                 # manipulating BEs).
@@ -1027,21 +1079,17 @@
                         status.append((_("Create backup boot environment:"),
                             bool_str(plan.backup_be)))
 
-                if not plan.new_be:
-                        cond_show(_("Services to change:"), "%d",
-                            len(plan.services))
-
         if "boot-archive" in disp:
                 status.append((_("Rebuild boot archive:"),
                     bool_str(plan.update_boot_archive)))
 
         # Right-justify all status strings based on length of longest string.
-	if status:
-		rjust_status = max(len(s[0]) for s in status)
-		rjust_value = max(len(s[1]) for s in status)
-		for s in status:
-			logger.info("%s %s" % (s[0].rjust(rjust_status),
-			    s[1].rjust(rjust_value)))
+        if status:
+                rjust_status = max(len(s[0]) for s in status)
+                rjust_value = max(len(s[1]) for s in status)
+                for s in status:
+                        logger.info("%s %s" % (s[0].rjust(rjust_status),
+                            s[1].rjust(rjust_value)))
                 # Ensure there is a blank line between status information and
                 # remainder.
                 logger.info("")
@@ -1066,7 +1114,7 @@
 
         if "fmris" in disp:
                 changed = collections.defaultdict(list)
-                for src, dest in itertools.chain(r, i, c):
+                for src, dest in itertools.chain(r, i, c, a):
                         if src and dest:
                                 if src.publisher != dest.publisher:
                                         pparent = "%s -> %s" % (src.publisher,
@@ -1074,8 +1122,9 @@
                                 else:
                                         pparent = dest.publisher
                                 pname = dest.pkg_stem
-                                pver = "%s -> %s" % (src.fmri.version,
-                                    dest.fmri.version)
+                                pver = str(src.fmri.version)
+                                if src != dest:
+                                        pver += " -> %s" % dest.fmri.version
                         elif dest:
                                 pparent = dest.publisher
                                 pname = dest.pkg_stem
@@ -1102,11 +1151,6 @@
                                 logger.info("    %s" % pver)
                                 last_parent = pparent
 
-                if len(a):
-                        logger.info(_("Affected fmris:"))
-                        for src, dest in a:
-                                logger.info("  %s", src)
-
         if "services" in disp and not plan.new_be:
                 last_action = None
                 for action, smf_fmri in plan.services:
@@ -1129,7 +1173,7 @@
                         for a in plan.get_release_notes():
                                 logger.info("  %s", a)
                 else:
-                        if not plan.new_be:
+                        if not plan.new_be and api_inst.is_liveroot and not DebugValues["GenerateNotesFile"]:
                                 logger.info(_("Release notes can be viewed with 'pkg history -n 1 -N'"))
                         else:
                                 tmp_path = __write_tmp_release_notes(plan)
@@ -1139,13 +1183,17 @@
                                 logger.info(_("After rebooting, use 'pkg history -n 1 -N' to view release notes."))
 
 def __write_tmp_release_notes(plan):
-        """write release notes out to a file in /tmp and return the name"""
+        """try to write release notes out to a file in /tmp and return the name"""
         if plan.has_release_notes:
                 try:
                         fd, path = tempfile.mkstemp(suffix=".txt", prefix="release-notes")
+                        # make file world readable
+                        os.chmod(path, 0644)
                         tmpfile = os.fdopen(fd, "w+b")
                         for a in plan.get_release_notes():
-                                tmpfile.write(a)
+                                if isinstance(a, unicode):
+                                        a = a.encode("utf-8")
+                                print >> tmpfile, a
                         tmpfile.close()
                         return path
                 except Exception:
@@ -1303,7 +1351,7 @@
                 else:
                         s = _("No updates necessary for this image.")
                 if api_inst.ischild():
-                        s + " (%s)" % api_inst.get_linked_name()
+                        s += " (%s)" % api_inst.get_linked_name()
                 msg(s)
                 return
 
@@ -1369,7 +1417,8 @@
                 api_inst.execute_plan()
                 rval = EXIT_OK
         except RuntimeError, e:
-                error(_("%s failed: %s") % (operation, e))
+                error(_("%(operation)s failed: %(err)s") %
+                    {"operation": operation, "err": e})
                 rval = EXIT_OOPS
         except (api_errors.InvalidPlanError,
             api_errors.ActionExecutionError,
@@ -1379,8 +1428,8 @@
                 error("\n" + str(e))
                 rval = EXIT_OOPS
         except (api_errors.LinkedImageException), e:
-                error(_("%s failed (linked image exception(s)):\n%s") %
-                      (operation, str(e)))
+                error(_("%(operation)s failed (linked image exception(s)):\n"
+                    "%(err)s") % {"operation": operation, "err": e})
                 rval = e.lix_exitrv
         except api_errors.ImageUpdateOnLiveImageException:
                 error(_("%s cannot be done on live image") % operation)
@@ -1418,7 +1467,8 @@
                 rval = EXIT_OOPS
         except Exception, e:
                 error(_("An unexpected error happened during "
-                    "%s: %s") % (operation, e))
+                    "%(operation)s: %(err)s") %
+                    {"operation": operation, "err": e})
                 raise
         finally:
                 exc_type = exc_value = exc_tb = None
@@ -1429,7 +1479,12 @@
 
                 try:
                         salvaged = api_inst.describe().salvaged
-                        if salvaged:
+			newbe = api_inst.describe().new_be
+                        if salvaged and (rval == EXIT_OK or not newbe):
+                                # Only show salvaged file list if populated
+                                # and operation was successful, or if operation
+                                # failed and a new BE was not created for
+                                # the operation.
                                 logger.error("")
                                 logger.error(_("The following unexpected or "
                                     "editable files and directories were\n"
@@ -1452,13 +1507,6 @@
 
 def __api_alloc(imgdir, exact_match, pkg_image_used):
 
-        def qv(val):
-                # Escape shell metacharacters; '\' must be escaped first to
-                # prevent escaping escapes.
-                for c in "\\ \t\n'`;&()|^<>?*":
-                        val = val.replace(c, "\\" + c)
-                return val
-
         progresstracker = get_tracker()
         try:
                 return api.ImageInterface(imgdir, CLIENT_API_VERSION,
@@ -1488,12 +1536,12 @@
                 error(_("No image rooted at '%s'") % e.user_dir, cmd=op)
                 return EXIT_OOPS
         if e_type == api_errors.InventoryException:
-                error("\n" + _("%s failed (inventory exception):\n%s") % (op,
-                    e))
+                error("\n" + _("%(operation)s failed (inventory exception):\n"
+                    "%(err)s") % {"operation": op, "err": e})
                 return EXIT_OOPS
         if isinstance(e, api_errors.LinkedImageException):
-                error(_("%s failed (linked image exception(s)):\n%s") %
-                      (op, str(e)))
+                error(_("%(operation)s failed (linked image exception(s)):\n"
+                    "%(err)s") % {"operation": op, "err": e})
                 return e.lix_exitrv
         if e_type == api_errors.IpkgOutOfDateException:
                 msg(_("""\
@@ -1799,624 +1847,6 @@
 
         return ret_code
 
-def opts_err_opt1_req_opt2(opt1, opt2, op):
-        txt = _("%(opt1)s may only be used in combination with %(opt2)s") % \
-            {"opt1": opt1, "opt2": opt2}
-        usage(txt, cmd=op)
-
-def opts_err_incompat(opt1, opt2, op):
-        txt = _("the %(opt1)s and %(opt2)s options may not be combined") % \
-            {"opt1": opt1, "opt2": opt2}
-        usage(txt, cmd=op)
-
-def opts_err_repeated(opt1, op):
-        txt = _("option '%s' repeated") % (opt1)
-        usage(txt, cmd=op)
-
-def opts_table_cb_beopts(op, api_inst, opts, opts_new):
-
-        # synthesize require_new_be and deny_new_be into new_be
-        del opts_new["require_new_be"]
-        del opts_new["deny_new_be"]
-        opts_new["new_be"] = None
-
-        if (opts["be_name"] or opts["require_new_be"]) and opts["deny_new_be"]:
-                opts_err_incompat("--require-new-be", "--deny-new-be", op)
-
-        # create a new key called "backup_be" in the options array
-        if opts["require_new_be"] or opts["be_name"]:
-                opts_new["new_be"] = True
-        if opts["deny_new_be"]:
-                opts_new["new_be"] = False
-
-        # synthesize require_backup_be and no_backup_be into backup_be
-        del opts_new["require_backup_be"]
-        del opts_new["no_backup_be"]
-        opts_new["backup_be"] = None
-
-        if (opts["require_backup_be"] or opts["backup_be_name"]) and \
-            opts["no_backup_be"]:
-                opts_err_incompat("--require-backup-be", "--no-backup-be", op)
-
-        if (opts["require_backup_be"] or opts["backup_be_name"]) and \
-            (opts["require_new_be"] or opts["be_name"]):
-                opts_err_incompat("--require-backup-be", "--require-new-be", op)
-
-        # create a new key called "backup_be" in the options array
-        if opts["require_backup_be"] or opts["backup_be_name"]:
-                opts_new["backup_be"] = True
-        if opts["no_backup_be"]:
-                opts_new["backup_be"] = False
-
-def opts_table_cb_li_ignore(op, api_inst, opts, opts_new):
-
-        # synthesize li_ignore_all and li_ignore_list into li_ignore
-        del opts_new["li_ignore_all"]
-        del opts_new["li_ignore_list"]
-        opts_new["li_ignore"] = None
-
-        # check if there's nothing to ignore
-        if not opts["li_ignore_all"] and not opts["li_ignore_list"]:
-                return
-
-        if opts["li_ignore_all"]:
-
-                # can't ignore all and specific images
-                if opts["li_ignore_list"]:
-                        opts_err_incompat("-I", "-i", op)
-
-                # can't ignore all and target anything.
-                if "li_target_all" in opts and opts["li_target_all"]:
-                        opts_err_incompat("-I", "-a", op)
-                if "li_target_list" in opts and opts["li_target_list"]:
-                        opts_err_incompat("-I", "-l", op)
-                if "li_name" in opts and opts["li_name"]:
-                        opts_err_incompat("-I", "-l", op)
-
-                opts_new["li_ignore"] = []
-                return
-
-        assert opts["li_ignore_list"]
-
-        # it doesn't make sense to specify images to ignore if the
-        # user is already specifying images to operate on.
-        if "li_target_all" in opts and opts["li_target_all"]:
-                opts_err_incompat("-i", "-a", op)
-        if "li_target_list" in opts and opts["li_target_list"]:
-                opts_err_incompat("-i", "-l", op)
-        if "li_name" in opts and opts["li_name"]:
-                opts_err_incompat("-i", "-l", op)
-
-        li_ignore = []
-        for li_name in opts["li_ignore_list"]:
-                # check for repeats
-                if li_name in li_ignore:
-                        opts_err_repeated("-i %s" % (li_name), op)
-                # add to ignore list
-                li_ignore.append(li_name)
-
-        opts_new["li_ignore"] = api_inst.parse_linked_name_list(li_ignore)
-
-def opts_table_cb_li_no_psync(op, api_inst, opts, opts_new):
-        # if a target child linked image was specified, the no-parent-sync
-        # option doesn't make sense since we know that both the parent and
-        # child image are accessible
-
-        if "li_target_all" not in opts:
-                # we don't accept linked image target options
-                assert "li_target_list" not in opts
-                return
-
-        if opts["li_target_all"] and not opts["li_parent_sync"]:
-                opts_err_incompat("-a", "--no-parent-sync", op)
-        if opts["li_target_list"] and not opts["li_parent_sync"]:
-                opts_err_incompat("-l", "--no-parent-sync", op)
-
-def opts_table_cb_li_props(op, api_inst, opts, opts_new):
-        """convert linked image prop list into a dictionary"""
-
-        opts_new["li_props"] = __parse_linked_props(opts["li_props"], op)
-
-def opts_table_cb_li_target(op, api_inst, opts, opts_new):
-        # figure out which option the user specified
-        if opts["li_target_all"] and opts["li_target_list"]:
-                opts_err_incompat("-a", "-l", op)
-        elif opts["li_target_all"]:
-                arg1 = "-a"
-        elif opts["li_target_list"]:
-                arg1 = "-l"
-        else:
-                return
-
-        if "be_activate" in opts and not opts["be_activate"]:
-                opts_err_incompat(arg1, "--no-be-activate", op)
-        if "be_name" in opts and opts["be_name"]:
-                opts_err_incompat(arg1, "--be-name", op)
-        if "deny_new_be" in opts and opts["deny_new_be"]:
-                opts_err_incompat(arg1, "--deny-new-be", op)
-        if "require_new_be" in opts and opts["require_new_be"]:
-                opts_err_incompat(arg1, "--require-new-be", op)
-        if "reject_pats" in opts and opts["reject_pats"]:
-                opts_err_incompat(arg1, "--reject", op)
-        if "origins" in opts and opts["origins"]:
-                opts_err_incompat(arg1, "-g", op)
-
-        # validate linked image name
-        li_target_list = []
-        for li_name in opts["li_target_list"]:
-                # check for repeats
-                if li_name in li_target_list:
-                        opts_err_repeated("-l %s" % (li_name), op)
-                # add to ignore list
-                li_target_list.append(li_name)
-
-        opts_new["li_target_list"] = \
-            api_inst.parse_linked_name_list(li_target_list)
-
-def opts_table_cb_li_target1(op, api_inst, opts, opts_new):
-        # figure out which option the user specified
-        if opts["li_name"]:
-                arg1 = "-l"
-        else:
-                return
-
-        if "be_activate" in opts and not opts["be_activate"]:
-                opts_err_incompat(arg1, "--no-be-activate", op)
-        if "be_name" in opts and opts["be_name"]:
-                opts_err_incompat(arg1, "--be-name", op)
-        if "deny_new_be" in opts and opts["deny_new_be"]:
-                opts_err_incompat(arg1, "--deny-new-be", op)
-        if "require_new_be" in opts and opts["require_new_be"]:
-                opts_err_incompat(arg1, "--require-new-be", op)
-        if "reject_pats" in opts and opts["reject_pats"]:
-                opts_err_incompat(arg1, "--require", op)
-        if "origins" in opts and opts["origins"]:
-                opts_err_incompat(arg1, "-g", op)
-
-def opts_table_cb_no_headers_vs_quiet(op, api_inst, opts, opts_new):
-        # check if we accept the -q option
-        if "quiet" not in opts:
-                return
-
-        # -q implies -H
-        if opts["quiet"]:
-                opts_new["omit_headers"] = True
-
-def opts_table_cb_q(op, api_inst, opts, opts_new):
-        # Be careful not to overwrite global_settings.client_output_quiet
-        # because it might be set "True" from elsewhere, e.g. in
-        # opts_table_cb_parsable.
-        if opts["quiet"] is True:
-                global_settings.client_output_quiet = True
-
-def opts_table_cb_v(op, api_inst, opts, opts_new):
-        global_settings.client_output_verbose = opts["verbose"]
-
-def opts_table_cb_nqv(op, api_inst, opts, opts_new):
-        if opts["verbose"] and opts["quiet"]:
-                opts_err_incompat("-v", "-q", op)
-
-def opts_table_cb_parsable(op, api_inst, opts, opts_new):
-        if opts["parsable_version"] and opts.get("verbose", False):
-                opts_err_incompat("--parsable", "-v", op)
-        if opts["parsable_version"]:
-                try:
-                        opts_new["parsable_version"] = int(
-                            opts["parsable_version"])
-                except ValueError:
-                        usage(_("--parsable expects an integer argument."),
-                            cmd=op)
-                global_settings.client_output_parsable_version = \
-                    opts_new["parsable_version"]
-                opts_new["quiet"] = True
-                global_settings.client_output_quiet = True
-
-def opts_table_cb_origins(op, api_inst, opts, opts_new):
-        origins = set()
-        for o in opts["origins"]:
-                origins.add(misc.parse_uri(o, cwd=orig_cwd))
-        opts_new["origins"] = origins
-
-def opts_table_cb_stage(op, api_inst, opts, opts_new):
-        if opts["stage"] == None:
-                opts_new["stage"] = API_STAGE_DEFAULT
-                return
-
-        if opts_new["stage"] not in api_stage_values:
-                usage(_("invalid operation stage: '%s'") % opts["stage"],
-                    cmd=op)
-
-def opts_cb_li_attach(op, api_inst, opts, opts_new):
-        if opts["attach_parent"] and opts["attach_child"]:
-                opts_err_incompat("-c", "-p", op)
-
-        if not opts["attach_parent"] and not opts["attach_child"]:
-                usage(_("either -c or -p must be specified"), cmd=op)
-
-        if opts["attach_child"]:
-                # if we're attaching a new child then that doesn't affect
-                # any other children, so ignoring them doesn't make sense.
-                if opts["li_ignore_all"]:
-                        opts_err_incompat("-c", "-I", op)
-                if opts["li_ignore_list"]:
-                        opts_err_incompat("-c", "-i", op)
-
-def opts_table_cb_md_only(op, api_inst, opts, opts_new):
-        # if the user didn't specify linked-md-only we're done
-        if not opts["li_md_only"]:
-                return
-
-        # li_md_only implies no li_pkg_updates
-        if "li_pkg_updates" in opts:
-                opts_new["li_pkg_updates"] = False
-
-        #
-        # if li_md_only is false that means we're not updating any packages
-        # within the current image so there are a ton of options that no
-        # longer apply to the current operation, and hence are incompatible
-        # with li_md_only.
-        #
-        arg1 = "--linked-md-only"
-        if "be_name" in opts and opts["be_name"]:
-                opts_err_incompat(arg1, "--be-name", op)
-        if "deny_new_be" in opts and opts["deny_new_be"]:
-                opts_err_incompat(arg1, "--deny-new-be", op)
-        if "require_new_be" in opts and opts["require_new_be"]:
-                opts_err_incompat(arg1, "--require-new-be", op)
-        if "li_parent_sync" in opts and not opts["li_parent_sync"]:
-                opts_err_incompat(arg1, "--no-parent-sync", op)
-        if "reject_pats" in opts and opts["reject_pats"]:
-                opts_err_incompat(arg1, "--reject", op)
-
-def opts_cb_list(op, api_inst, opts, opts_new):
-        if opts_new["origins"] and opts_new["list_upgradable"]:
-                opts_err_incompat("-g", "-u", op)
-
-        if opts_new["origins"] and not opts_new["list_newest"]:
-                # Use of -g implies -a unless -n is provided.
-                opts_new["list_installed_newest"] = True
-
-        if opts_new["list_all"] and not opts_new["list_installed_newest"]:
-                opts_err_opt1_req_opt2("-f", "-a", op)
-
-        if opts_new["list_installed_newest"] and opts_new["list_newest"]:
-                opts_err_incompat("-a", "-n", op)
-
-        if opts_new["list_installed_newest"] and opts_new["list_upgradable"]:
-                opts_err_incompat("-a", "-u", op)
-
-        if opts_new["summary"] and opts_new["verbose"]:
-                opts_err_incompat("-s", "-v", op)
-
-def opts_cb_int(k, op, api_inst, opts, opts_new, minimum=None):
-        if k not in opts:
-                usage(_("missing required parameter: %s" % k), cmd=op)
-                return
-
-        # get the original argument value
-        v = opts[k]
-
-        # make sure it is an integer
-        try:
-                v = int(v)
-        except (ValueError, TypeError):
-                # not a valid integer
-                err = _("invalid '%s' value: %s") % (k, v)
-                usage(err, cmd=op)
-
-        # check the minimum bounds
-        if minimum is not None and v < minimum:
-                err = _("'%s' must be >= %d") % (k, minimum)
-                usage(err, cmd=op)
-
-        # update the new options array to make the value an integer
-        opts_new[k] = v
-
-def opts_cb_fd(k, op, api_inst, opts, opts_new):
-        opts_cb_int(k, op, api_inst, opts, opts_new, minimum=0)
-
-        err = _("invalid '%s' value: %s") % (k, opts_new[k])
-        try:
-                os.fstat(opts_new[k])
-        except OSError:
-                # not a valid file descriptor
-                usage(err, cmd=op)
-
-def opts_cb_remote(op, api_inst, opts, opts_new):
-        opts_cb_fd("ctlfd", op, api_inst, opts, opts_new)
-        opts_cb_fd("progfd", op, api_inst, opts, opts_new)
-
-        # move progfd from opts_new into a global
-        global_settings.client_output_progfd = opts_new["progfd"]
-        del opts_new["progfd"]
-
-def opts_table_cb_concurrency(op, api_inst, opts, opts_new):
-        if opts["concurrency"] is None:
-                # remove concurrency from parameters dict
-                del opts_new["concurrency"]
-                return
-
-        # make sure we have an integer
-        opts_cb_int("concurrency", op, api_inst, opts, opts_new)
-
-        # update global concurrency setting
-        global_settings.client_concurrency = opts_new["concurrency"]
-
-        # remove concurrency from parameters dict
-        del opts_new["concurrency"]
-
-#
-# options common to multiple pkg(1) subcommands.  The format for specifying
-# options is a list which can contain:
-#
-# - Function pointers which define callbacks that are invoked after all
-#   options (aside from extra pargs) have been parsed.  These callbacks can
-#   verify the the contents and combinations of different options.
-#
-# - Tuples formatted as:
-#       (s, l, k, v)
-#   where the values are:
-#       s: a short option, ex: -f
-#       l: a long option, ex: --foo
-#       k: the key value for the options dictionary
-#       v: the default value. valid values are: True/False, None, [], 0
-#
-opts_table_beopts = [
-    opts_table_cb_beopts,
-    ("",  "backup-be-name=",   "backup_be_name",     None),
-    ("",  "be-name=",          "be_name",            None),
-    ("",  "deny-new-be",       "deny_new_be",        False),
-    ("",  "no-backup-be",      "no_backup_be",       False),
-    ("",  "no-be-activate",    "be_activate",        True),
-    ("",  "require-backup-be", "require_backup_be",  False),
-    ("",  "require-new-be",    "require_new_be",     False),
-]
-
-opts_table_concurrency = [
-    opts_table_cb_concurrency,
-    ("C", "concurrency=",      "concurrency",        None),
-]
-
-opts_table_force = [
-    ("f", "",                "force",                False),
-]
-
-opts_table_li_ignore = [
-    opts_table_cb_li_ignore,
-    ("I", "",                "li_ignore_all",        False),
-    ("i", "",                "li_ignore_list",       []),
-]
-
-opts_table_li_md_only = [
-    opts_table_cb_md_only,
-    ("",  "linked-md-only",    "li_md_only",         False),
-]
-
-opts_table_li_no_pkg_updates = [
-    ("",  "no-pkg-updates",  "li_pkg_updates",       True),
-]
-
-opts_table_li_no_psync = [
-    opts_table_cb_li_no_psync,
-    ("",  "no-parent-sync",  "li_parent_sync",       True),
-]
-
-opts_table_li_props = [
-    opts_table_cb_li_props,
-    ("", "prop-linked",      "li_props",             []),
-]
-
-opts_table_li_target = [
-    opts_table_cb_li_target,
-    ("a", "",                "li_target_all",        False),
-    ("l", "",                "li_target_list",       []),
-]
-
-opts_table_li_target1 = [
-    opts_table_cb_li_target1,
-    ("l", "",                "li_name",              None),
-]
-
-opts_table_licenses = [
-    ("",  "accept",          "accept",               False),
-    ("",  "licenses",        "show_licenses",        False),
-]
-
-opts_table_no_headers = [
-    opts_table_cb_no_headers_vs_quiet,
-    ("H", "",                "omit_headers",         False),
-]
-
-opts_table_no_index = [
-    ("",  "no-index",        "update_index",         True),
-]
-
-opts_table_no_refresh = [
-    ("",  "no-refresh",      "refresh_catalogs",     True),
-]
-
-opts_table_reject = [
-    ("", "reject=",          "reject_pats",          []),
-]
-
-opts_table_verbose = [
-    opts_table_cb_v,
-    ("v", "",                "verbose",              0),
-]
-
-opts_table_quiet = [
-    opts_table_cb_q,
-    ("q", "",                "quiet",                False),
-]
-
-opts_table_parsable = [
-    opts_table_cb_parsable,
-    ("", "parsable=",        "parsable_version",     None),
-]
-
-opts_table_nqv = \
-    opts_table_quiet + \
-    opts_table_verbose + \
-    [
-    opts_table_cb_nqv,
-    ("n", "",                "noexecute",            False),
-]
-
-opts_table_origins = [
-    opts_table_cb_origins,
-    ("g", "",                "origins",              []),
-]
-
-opts_table_stage = [
-    opts_table_cb_stage,
-    ("",  "stage",           "stage",                None),
-]
-
-#
-# Options for pkg(1) subcommands.  Built by combining the option tables above,
-# with some optional subcommand unique options defined below.
-#
-opts_install = \
-    opts_table_beopts + \
-    opts_table_concurrency + \
-    opts_table_li_ignore + \
-    opts_table_li_no_psync + \
-    opts_table_licenses + \
-    opts_table_reject + \
-    opts_table_no_index + \
-    opts_table_no_refresh + \
-    opts_table_nqv + \
-    opts_table_parsable + \
-    opts_table_origins + \
-    []
-
-# "update" cmd inherits all "install" cmd options
-opts_update = \
-    opts_install + \
-    opts_table_force + \
-    opts_table_stage + \
-    []
-
-# "attach-linked" cmd inherits all "install" cmd options
-opts_attach_linked = \
-    opts_install + \
-    opts_table_force + \
-    opts_table_li_md_only + \
-    opts_table_li_no_pkg_updates + \
-    opts_table_li_props + \
-    [
-    opts_cb_li_attach,
-    ("",  "allow-relink",   "allow_relink",         False),
-    ("c", "",               "attach_child",         False),
-    ("p", "",               "attach_parent",        False),
-]
-
-opts_list_mediator = \
-    opts_table_no_headers + \
-    [
-    ("a", "",                "list_available",      False),
-    ("F", "output-format",   "output_format",       None)
-]
-
-opts_revert = \
-    opts_table_beopts + \
-    opts_table_nqv + \
-    opts_table_parsable + \
-    [
-    ("",  "tagged",          "tagged",               False),
-]
-
-opts_set_mediator = \
-    opts_table_beopts + \
-    opts_table_no_index + \
-    opts_table_nqv + \
-    opts_table_parsable + \
-    [
-    ("I", "implementation",  "med_implementation",   None),
-    ("V", "version",         "med_version",          None)
-]
-
-opts_unset_mediator = \
-    opts_table_beopts + \
-    opts_table_no_index + \
-    opts_table_nqv + \
-    opts_table_parsable + \
-    [
-    ("I", "",               "med_implementation",   False),
-    ("V", "",               "med_version",          False)
-]
-
-# "set-property-linked" cmd inherits all "install" cmd options
-opts_set_property_linked = \
-    opts_install + \
-    opts_table_li_md_only + \
-    opts_table_li_no_pkg_updates + \
-    opts_table_li_target1 + \
-    []
-
-# "sync-linked" cmd inherits all "install" cmd options
-opts_sync_linked = \
-    opts_install + \
-    opts_table_li_md_only + \
-    opts_table_li_no_pkg_updates + \
-    opts_table_li_target + \
-    opts_table_stage + \
-    []
-
-opts_uninstall = \
-    opts_table_beopts + \
-    opts_table_concurrency + \
-    opts_table_li_ignore + \
-    opts_table_no_index + \
-    opts_table_nqv + \
-    opts_table_parsable + \
-    opts_table_stage
-
-opts_audit_linked = \
-    opts_table_li_no_psync + \
-    opts_table_li_target + \
-    opts_table_no_headers + \
-    opts_table_quiet + \
-    []
-
-opts_detach_linked = \
-    opts_table_force + \
-    opts_table_li_target + \
-    opts_table_nqv + \
-    []
-
-opts_list_linked = \
-    opts_table_li_ignore + \
-    opts_table_no_headers + \
-    []
-
-opts_list_property_linked = \
-    opts_table_li_target1 + \
-    opts_table_no_headers + \
-    []
-
-opts_list_inventory = \
-    opts_table_li_no_psync + \
-    opts_table_no_refresh + \
-    opts_table_no_headers + \
-    opts_table_origins + \
-    opts_table_verbose + \
-    [
-    opts_cb_list,
-    ("a", "",               "list_installed_newest", False),
-    ("f", "",               "list_all",              False),
-    ("n", "",               "list_newest",           False),
-    ("s", "",               "summary",               False),
-    ("u", "",               "list_upgradable",       False),
-]
-
-opts_remote = [
-    opts_cb_remote,
-    ("",  "ctlfd",           "ctlfd",                None),
-    ("",  "progfd",          "progfd",               None),
-]
-
-
 class RemoteDispatch(object):
         """RPC Server Class which invoked by the PipedRPCServer when a RPC
         request is recieved."""
@@ -2481,6 +1911,19 @@
 def remote(op, api_inst, pargs, ctlfd):
         """Execute commands from a remote pipe"""
 
+        #
+        # this is kinda a gross hack.  SocketServer.py uses select.select()
+        # which doesn't support file descriptors larger than FD_SETSIZE.
+        # Since ctlfd may have been allocated in a parent process with many
+        # file descriptors, it may be larger than FD_SETSIZE.  Here in the
+        # child, though, the majority of those have been closed, so os.dup()
+        # should return a lower-numbered descriptor which will work with
+        # select.select().
+        #
+        ctlfd_new = os.dup(ctlfd)
+        os.close(ctlfd)
+        ctlfd = ctlfd_new
+
         rpc_server = pipeutils.PipedRPCServer(ctlfd)
         rpc_server.register_introspection_functions()
         rpc_server.register_instance(RemoteDispatch())
@@ -2516,8 +1959,8 @@
 
                 # make sure the user didn't specify duplicate variants
                 if name in variants:
-                        usage(_("%s: duplicate variant specified: %s") %
-                            (op, name))
+                        usage(_("%(subcmd)s: duplicate variant specified: "
+                            "%(variant)s") % {"subcmd": op, "variant": name})
                 variants[name] = value
 
         return __api_op(op, api_inst, _accept=accept, _li_ignore=li_ignore,
@@ -2616,7 +2059,8 @@
 
 def uninstall(op, api_inst, pargs,
     be_activate, backup_be, backup_be_name, be_name, new_be, li_ignore,
-    update_index, noexecute, parsable_version, quiet, verbose, stage):
+    li_parent_sync, update_index, noexecute, parsable_version, quiet,
+    verbose, stage):
         """Attempt to take package specified to DELETED state."""
 
         if not pargs:
@@ -2633,7 +2077,8 @@
             _noexecute=noexecute, _quiet=quiet, _stage=stage,
             _verbose=verbose, backup_be=backup_be,
             backup_be_name=backup_be_name, be_activate=be_activate,
-            be_name=be_name, new_be=new_be, _parsable_version=parsable_version,
+            be_name=be_name, li_parent_sync=li_parent_sync, new_be=new_be,
+            _parsable_version=parsable_version,
             pkgs_to_uninstall=pargs, update_index=update_index)
 
 def update(op, api_inst, pargs, accept, backup_be, backup_be_name, be_activate,
@@ -2980,8 +2425,10 @@
         for a in api_inst.get_avoid_list():
                 tracking = " ".join(a[1])
                 if tracking:
-                        logger.info(_("    %s (group dependency of '%s')")
-                            % (a[0], tracking))
+                        logger.info(_(
+                            "    %(avoid_pkg)s (group dependency of "
+                            "'%(tracking_pkg)s')")
+                            % {"avoid_pkg": a[0], "tracking_pkg": tracking})
                 else:
                         logger.info("    %s" % a[0])
 
@@ -3249,8 +2696,14 @@
 
         searches = []
 
+        # Strip pkg:/ or pkg:/// from the fmri.
+        # If fmri has pkg:// then strip the prefix
+        # from 'pkg://' upto the first slash.
+
+        qtext = re.sub(r"pkg:///|pkg://[^/]*/|pkg:/", "", " ".join(pargs))
+
         try:
-                query = [api.Query(" ".join(pargs), case_sensitive,
+                query = [api.Query(qtext, case_sensitive,
                     return_actions)]
         except api_errors.BooleanQueryException, e:
                 error(e)
@@ -3402,14 +2855,18 @@
         info_local = False
         info_remote = False
         origins = set()
-
-        opts, pargs = getopt.getopt(args, "g:lr", ["license"])
+        quiet = False
+
+        opts, pargs = getopt.getopt(args, "g:lqr", ["license"])
         for opt, arg in opts:
                 if opt == "-g":
                         origins.add(misc.parse_uri(arg, cwd=orig_cwd))
                         info_remote = True
                 elif opt == "-l":
                         info_local = True
+                elif opt == "-q":
+                        quiet = True
+                        global_settings.client_output_quiet = True
                 elif opt == "-r":
                         info_remote = True
                 elif opt == "--license":
@@ -3426,6 +2883,10 @@
 
         err = 0
 
+        # Reset the progress tracker here, because we may have to switch to a
+        # different tracker due to the options parse.
+        _api_inst.progresstracker = get_tracker()
+
         api_inst.progresstracker.set_purpose(
             api_inst.progresstracker.PURPOSE_LISTING)
 
@@ -3462,17 +2923,20 @@
 
         no_licenses = []
         for i, pi in enumerate(pis):
-                if i > 0:
+                if not quiet and i > 0:
                         msg("")
 
                 if display_license:
                         if not pi.licenses:
                                 no_licenses.append(pi.fmri)
-                        else:
+                        elif not quiet:
                                 for lic in pi.licenses:
                                         msg(lic)
                         continue
 
+                if quiet:
+                        continue
+
                 state = ""
                 if api.PackageInfo.INSTALLED in pi.states:
                         state = _("Installed")
@@ -3548,32 +3012,36 @@
         if notfound:
                 if pis:
                         err = EXIT_PARTIAL
-                        logger.error("")
+                        if not quiet:
+                                logger.error("")
                 else:
                         err = EXIT_OOPS
 
-                if info_local:
-                        logger.error(_("""\
+                if not quiet:
+                        if info_local:
+                                logger.error(_("""\
 pkg: info: no packages matching the following patterns you specified are
 installed on the system.  Try specifying -r to query remotely:"""))
-                elif info_remote:
-                        logger.error(_("""\
+                        elif info_remote:
+                                logger.error(_("""\
 pkg: info: no packages matching the following patterns you specified were
 found in the catalog.  Try relaxing the patterns, refreshing, and/or
 examining the catalogs:"""))
-                logger.error("")
-                for p in notfound:
-                        logger.error("        %s" % p)
+                        logger.error("")
+                        for p in notfound:
+                                logger.error("        %s" % p)
 
         if no_licenses:
                 if len(no_licenses) == len(pis):
                         err = EXIT_OOPS
                 else:
                         err = EXIT_PARTIAL
-                error(_("no license information could be found for the "
-                    "following packages:"))
-                for pfmri in no_licenses:
-                        logger.error("\t%s" % pfmri)
+
+                if not quiet:
+                        error(_("no license information could be found for the "
+                            "following packages:"))
+                        for pfmri in no_licenses:
+                                logger.error("\t%s" % pfmri)
         return err
 
 def calc_widths(lines, attrs, widths=None):
@@ -3599,7 +3067,7 @@
                 return JUST_UNKNOWN
         return [ __chose_just(attr) for attr in attrs ]
 
-def produce_lines(actionlist, attrs, action_types=None, show_all=False,
+def produce_lines(actionlist, attrs, show_all=False,
     remove_consec_dup_lines=False, last_res=None):
         """Produces a list of n tuples (where n is the length of attrs)
         containing the relevant information about the actions.
@@ -3613,16 +3081,13 @@
         The "attrs" parameter is a list of the attributes of the action that
         should be displayed.
 
-        The "action_types" parameter may contain a list of the types of actions
-        that should be displayed.
-
         The "show_all" parameter determines whether an action that lacks one
         or more of the desired attributes will be displayed or not.
 
         The "remove_consec_dup_lines" parameter determines whether consecutive
         duplicate lines should be removed from the results.
 
-        The "last_res" paramter is a seed to compare the first result against
+        The "last_res" parameter is a seed to compare the first result against
         for duplicate removal.
         """
 
@@ -3633,8 +3098,6 @@
         if last_res:
                 lines.append(last_res)
         for pfmri, action, pub, match, match_type in actionlist:
-                if action_types and action.name not in action_types:
-                        continue
                 line = []
                 for attr in attrs:
                         if action and attr in action.attrs:
@@ -3758,13 +3221,12 @@
         fmt.rstrip("\t")
         return fmt
 
-def display_contents_results(actionlist, attrs, sort_attrs, action_types,
-    display_headers):
+def display_contents_results(actionlist, attrs, sort_attrs, display_headers):
         """Print results of a "list" operation.  Returns False if no output
         was produced."""
 
         justs = calc_justs(attrs)
-        lines = produce_lines(actionlist, attrs, action_types)
+        lines = produce_lines(actionlist, attrs)
         widths = calc_widths(lines, attrs)
 
         if sort_attrs:
@@ -3961,6 +3423,9 @@
                 api_inst.log_operation_end(
                     result=RESULT_FAILED_UNKNOWN)
                 return EXIT_OOPS
+        except api_errors.CatalogRefreshException, e:
+                display_catalog_failures(e)
+                return EXIT_OOPS
         except api_errors.InventoryException, e:
                 if e.illegal:
                         for i in e.illegal:
@@ -3976,22 +3441,49 @@
                             result=RESULT_NOTHING_TO_DO)
                         return EXIT_OOPS
 
-        actionlist = [
-            (m.fmri, a, None, None, None)
-            for m in manifests
-            for a in m.gen_actions(excludes)
-            if mmatches(a)
-        ]
+        # Build a generator expression based on whether specific action types
+        # were provided.
+        if action_types:
+                # If query is limited to specific action types, use the more
+                # efficient type-based generation mechanism.
+                gen_expr = (
+                    (m.fmri, a, None, None, None)
+                    for m in manifests
+                    for a in m.gen_actions_by_types(action_types,
+                        excludes=excludes)
+                    if mmatches(a)
+                )
+        else:
+                gen_expr = (
+                    (m.fmri, a, None, None, None)
+                    for m in manifests
+                    for a in m.gen_actions(excludes=excludes)
+                    if mmatches(a)
+                )
+
+        # Determine if the query returned any results by "peeking" at the first
+        # value returned from the generator expression.
+        try:
+                found = gen_expr.next()
+        except StopIteration:
+                found = None
+                actionlist = []
+
+        if found:
+                # If any matching entries were found, create a new generator
+                # expression using itertools.chain that includes the first
+                # result.
+                actionlist = itertools.chain([found], gen_expr)
 
         rval = EXIT_OK
-        if attr_match and manifests and not actionlist:
+        if attr_match and manifests and not found:
                 rval = EXIT_OOPS
                 logger.error(_("""\
 pkg: contents: no matching actions found in the listed packages"""))
 
         if manifests and rval == EXIT_OK:
                 displayed_results = display_contents_results(actionlist, attrs,
-                    sort_attrs, action_types, display_headers)
+                    sort_attrs, display_headers)
 
                 if not displayed_results:
                         if output_fields:
@@ -4037,8 +3529,8 @@
         total = cre.total
         succeeded = cre.succeeded
 
-        txt = _("pkg: %s/%s catalogs successfully updated:") % (succeeded,
-            total)
+        txt = _("pkg: %(succeeded)s/%(total)s catalogs successfully "
+            "updated:") % {"succeeded": succeeded, "total": total}
         if cre.failed:
                 # This ensures that the text gets printed before the errors.
                 logger.error(txt)
@@ -4261,6 +3753,9 @@
                                 remove_mirrors.add(misc.parse_uri(arg,
                                     cwd=orig_cwd))
                 elif opt == "-p":
+			if repo_uri:
+                                usage(_("The -p option can be specified only "
+				    "once."), cmd=cmd_name) 
                         repo_uri = misc.parse_uri(arg, cwd=orig_cwd)
                 elif opt in ("-P", "--search-first"):
                         search_first = True
@@ -4473,28 +3968,16 @@
                         search_after = prefix
                         search_before = None
                 else:
-                        # The update case is special and requires some
-                        # finesse.  In particular, the update should
-                        # only happen if the repo_uri specified is
-                        # already known to the existing publisher.  This
-                        # is just a sanity check to ensure that random
-                        # repositories can't attempt to hijack other
-                        # publishers.
+                        add_origins = []
+                        add_mirrors = []
                         dest_pub = api_inst.get_publisher(prefix=prefix,
                             duplicate=True)
                         dest_repo = dest_pub.repository
-
                         if dest_repo.origins and \
                             not dest_repo.has_origin(repo_uri):
-                                failed.append((prefix, _("""\
-    The specified repository location is not a known source of publisher
-    configuration updates for '%s'.
-
-    This new repository location must be added as an origin to the publisher
-    to accept configuration updates from this repository.""") % prefix))
-                                continue
-
-                        if not src_repo:
+                                add_origins = [repo_uri]
+
+                        if not src_repo and not add_origins:
                                 # The repository doesn't have to provide origin
                                 # information for publishers.  If it doesn't,
                                 # the origin of every publisher returned is
@@ -4503,10 +3986,7 @@
                                 # nothing special needs to be done.
                                 if not dest_repo.origins:
                                         add_origins = [repo_uri]
-                                else:
-                                        add_origins = []
-                                add_mirrors = []
-                        else:
+                        elif src_repo:
                                 # Avoid duplicates by adding only those mirrors
                                 # or origins not already known.
                                 add_mirrors = [
@@ -4753,12 +4233,17 @@
 def publisher_unset(api_inst, args):
         """pkg unset-publisher publisher ..."""
 
-        if len(args) == 0:
+        opts, pargs = getopt.getopt(args, "")
+        if not pargs:
                 usage(_("at least one publisher must be specified"),
                     cmd="unset-publisher")
 
         errors = []
+        goal = len(args)
+        progtrack = api_inst.progresstracker
+        progtrack.job_start(progtrack.JOB_PKG_CACHE, goal=goal)
         for name in args:
+
                 try:
                         api_inst.remove_publisher(prefix=name, alias=name)
                 except api_errors.ImageFormatUpdateNeeded, e:
@@ -4768,7 +4253,10 @@
                     api_errors.PublisherError,
                     api_errors.ModifyingSyspubException), e:
                         errors.append((name, e))
-
+                finally:
+                        progtrack.job_add_progress(progtrack.JOB_PKG_CACHE)
+
+        progtrack.job_done(progtrack.JOB_PKG_CACHE)
         retcode = EXIT_OK
         if errors:
                 if len(errors) == len(args):
@@ -5294,72 +4782,153 @@
 
         return EXIT_OK
 
-def variant_list(api_inst, args):
-        """pkg variant [-H] [<variant_spec>]"""
-
-        omit_headers = False
-
-        opts, pargs = getopt.getopt(args, "H")
-
-        for opt, arg in opts:
-                if opt == "-H":
-                        omit_headers = True
-
-        # XXX image variants should be accessible through pkg.client.api
-        variants = img.get_variants()
-
-        for p in pargs:
-                if p not in variants:
-                        error(_("no such variant: %s") % p, cmd="variant")
-                        return EXIT_OOPS
-
-        if not pargs:
-                pargs = variants.keys()
-
-        width = max(max([len(p) for p in pargs]), 8)
-        fmt = "%%-%ss %%s" % width
-        if not omit_headers:
-                msg(fmt % ("VARIANT", "VALUE"))
-
-        for p in pargs:
-                msg(fmt % (p, variants[p]))
-
+def list_variant(op, api_inst, pargs, omit_headers, output_format,
+    list_all_items, list_installed, verbose):
+        """pkg variant [-Haiv] [-F format] [<variant_pattern> ...]"""
+
+        subcommand = "variant"
+        if output_format is None:
+                output_format = "default"
+
+        # To work around Python 2.x's scoping limits, a list is used.
+        found = [False]
+        req_variants = set(pargs)
+
+        def gen_current():
+                for (name, val, pvals) in api_inst.gen_variants(variant_list,
+                    patterns=req_variants):
+                        found[0] = True
+                        yield {
+                            "variant": name,
+                            "value": val
+                        }
+
+        def gen_possible():
+                for (name, val, pvals) in api_inst.gen_variants(variant_list,
+                    patterns=req_variants):
+                        found[0] = True
+                        for pval in pvals:
+                                yield {
+                                    "variant": name,
+                                    "value": pval
+                                }
+
+        if verbose:
+                gen_listing = gen_possible
+        else:
+                gen_listing = gen_current
+
+        if list_all_items:
+                if verbose:
+                        variant_list = api_inst.VARIANT_ALL_POSSIBLE
+                else:
+                        variant_list = api_inst.VARIANT_ALL
+        elif list_installed:
+                if verbose:
+                        variant_list = api_inst.VARIANT_INSTALLED_POSSIBLE
+                else:
+                        variant_list = api_inst.VARIANT_INSTALLED
+        else:
+                if verbose:
+                        variant_list = api_inst.VARIANT_IMAGE_POSSIBLE
+                else:
+                        variant_list = api_inst.VARIANT_IMAGE
+
+        #    VARIANT VALUE
+        #    <variant> <value>
+        #    <variant_2> <value_2>
+        #    ...
+        field_data = {
+            "variant" : [("default", "json", "tsv"), _("VARIANT"), ""],
+            "value" : [("default", "json", "tsv"), _("VALUE"), ""],
+        }
+        desired_field_order = (_("VARIANT"), _("VALUE"))
+
+        # Default output formatting.
+        def_fmt = "%-70s %s"
+
+        # print without trailing newline.
+        sys.stdout.write(misc.get_listing(desired_field_order,
+            field_data, gen_listing(), output_format, def_fmt,
+            omit_headers))
+
+        if not found[0] and req_variants:
+                if output_format == "default":
+                        # Don't pollute other output formats.
+                        error(_("no matching variants found"),
+                            cmd=subcommand)
+                return EXIT_OOPS
+
+        # Successful if no variants exist or if at least one matched.
         return EXIT_OK
 
-def facet_list(api_inst, args):
-        """pkg facet [-H] [<facet_spec>]"""
-
-        omit_headers = False
-
-        opts, pargs = getopt.getopt(args, "H")
-
-        for opt, arg in opts:
-                if opt == "-H":
-                        omit_headers = True
-
-        # XXX image facets should be accessible through pkg.client.api
-        facets = img.get_facets()
-
-        for i, p in enumerate(pargs[:]):
-                if not p.startswith("facet."):
-                        pargs[i] = "facet." + p
-
-        if not pargs:
-                pargs = facets.keys()
-
-        if pargs:
-                width = max(max([len(p) for p in pargs]), 8)
-        else:
-                width = 8
-
-        fmt = "%%-%ss %%s" % width
-
-        if not omit_headers:
-                msg(fmt % ("FACETS", "VALUE"))
-
-        for p in pargs:
-                msg(fmt % (p, facets[p]))
-
+def list_facet(op, api_inst, pargs, omit_headers, output_format, list_all_items,
+    list_masked, list_installed):
+        """pkg facet [-Hai] [-F format] [<facet_pattern> ...]"""
+
+        subcommand = "facet"
+        if output_format is None:
+                output_format = "default"
+
+        # To work around Python 2.x's scoping limits, a list is used.
+        found = [False]
+        req_facets = set(pargs)
+
+        facet_list = api_inst.FACET_IMAGE
+        if list_all_items:
+                facet_list = api_inst.FACET_ALL
+        elif list_installed:
+                facet_list = api_inst.FACET_INSTALLED
+
+        def gen_listing():
+                for (name, val, src, masked) in \
+                    api_inst.gen_facets(facet_list, patterns=req_facets):
+                        found[0] = True
+
+                        if not list_masked and masked:
+                                continue
+
+                        # "value" and "masked" are intentionally not _().
+                        yield {
+                            "facet": name,
+                            "value": val and "True" or "False",
+                            "src": src,
+                            "masked": masked and "True" or "False",
+                        }
+
+        #    FACET VALUE
+        #    <facet> <value> <src>
+        #    <facet_2> <value_2> <src2>
+        #    ...
+        field_data = {
+            "facet"  : [("default", "json", "tsv"), _("FACET"), ""],
+            "value"  : [("default", "json", "tsv"), _("VALUE"), ""],
+            "src"    : [("default", "json", "tsv"), _("SRC"), ""],
+        }
+        desired_field_order = (_("FACET"), _("VALUE"), _("SRC"))
+        def_fmt = "%-64s %-5s %s"
+
+        if list_masked:
+                # if we're displaying masked facets, we should also mark which
+                # facets are masked in the output.
+                field_data["masked"] = \
+                    [("default", "json", "tsv"), _("MASKED"), ""]
+                desired_field_order += (_("MASKED"),)
+                def_fmt = "%-57s %-5s %-6s %-s"
+
+        # print without trailing newline.
+        sys.stdout.write(misc.get_listing(desired_field_order,
+            field_data, gen_listing(), output_format, def_fmt,
+            omit_headers))
+
+        if not found[0] and req_facets:
+                if output_format == "default":
+                        # Don't pollute other output formats.
+                        error(_("no matching facets found"),
+                            cmd=subcommand)
+                return EXIT_OOPS
+
+        # Successful if no facets exist or if at least one matched.
         return EXIT_OK
 
 def list_linked(op, api_inst, pargs,
@@ -5570,8 +5139,8 @@
                     update_index=update_index)
 
         # sync the requested child image(s)
-	api_inst.progresstracker.set_major_phase(
-	    api_inst.progresstracker.PHASE_UTILITY)
+        api_inst.progresstracker.set_major_phase(
+            api_inst.progresstracker.PHASE_UTILITY)
         rvdict = api_inst.sync_linked_children(li_target_list,
             noexecute=noexecute, accept=accept, show_licenses=show_licenses,
             refresh_catalogs=refresh_catalogs, update_index=update_index,
@@ -5641,8 +5210,8 @@
                     reject_list=reject_pats, update_index=update_index)
 
         # attach the requested child image
-	api_inst.progresstracker.set_major_phase(
-	    api_inst.progresstracker.PHASE_UTILITY)
+        api_inst.progresstracker.set_major_phase(
+            api_inst.progresstracker.PHASE_UTILITY)
         (rv, err, p_dict) = api_inst.attach_linked_child(lin, li_path, li_props,
             accept=accept, allow_relink=allow_relink, force=force,
             li_md_only=li_md_only, li_pkg_updates=li_pkg_updates,
@@ -5662,8 +5231,8 @@
                         return EXIT_OOPS
         return rv
 
-def detach_linked(op, api_inst, pargs, force, li_target_all, li_target_list,
-    noexecute, quiet, verbose):
+def detach_linked(op, api_inst, pargs, force, li_md_only, li_pkg_updates,
+    li_target_all, li_target_list, noexecute, quiet, verbose):
         """pkg detach-linked
             [-fnvq] [-a|-l <li-name>] [--linked-md-only]
 
@@ -5672,11 +5241,13 @@
         if not li_target_all and not li_target_list:
                 # detach the current image
                 return __api_op(op, api_inst, _noexecute=noexecute,
-                    _quiet=quiet, _verbose=verbose, force=force)
-
-	api_inst.progresstracker.set_major_phase(
-	    api_inst.progresstracker.PHASE_UTILITY)
+                    _quiet=quiet, _verbose=verbose, force=force,
+                    li_md_only=li_md_only, li_pkg_updates=li_pkg_updates)
+
+        api_inst.progresstracker.set_major_phase(
+            api_inst.progresstracker.PHASE_UTILITY)
         rvdict = api_inst.detach_linked_children(li_target_list, force=force,
+            li_md_only=li_md_only, li_pkg_updates=li_pkg_updates,
             noexecute=noexecute)
 
         rv, err, p_dicts = api_inst.detach_linked_rvdict2rv(rvdict)
@@ -5710,15 +5281,16 @@
         set_props = {}
         version = None
 
-        opts, pargs = getopt.getopt(args, "fFPUza:g:m:p:k:c:",
-            ["force", "full", "partial", "user", "zone", "authority=", "facet=",
-                "mirror=", "origin=", "publisher=", "no-refresh", "variant=",
+        opts, pargs = getopt.getopt(args, "fFPUzg:m:p:k:c:",
+            ["force", "full", "partial", "user", "zone", "facet=", "mirror=",
+                "origin=", "publisher=", "no-refresh", "variant=",
                 "set-property="])
 
         for opt, arg in opts:
-                # -a is deprecated and will be removed at a future date.
-                if opt in ("-a", "-p", "--publisher"):
-                        pub_url = None
+                if opt in ("-p", "--publisher"):
+			if pub_url:
+                                usage(_("The -p option can be specified only "
+				    "once."), cmd=cmd_name)
                         try:
                                 pub_name, pub_url = arg.split("=", 1)
                         except ValueError:
@@ -5791,7 +5363,7 @@
                     cmd=cmd_name)
         image_dir = pargs[0]
 
-        if not pub_name and not refresh_allowed:
+        if pub_url and not pub_name and not refresh_allowed:
                 usage(_("--no-refresh cannot be used with -p unless a "
                     "publisher prefix is provided."), cmd=cmd_name)
 
@@ -6252,82 +5824,228 @@
 orig_cwd = None
 
 #
+# Mapping of the internal option name to short and long CLI options.
+#
+# {option_name: (short, long)}
+#
+#
+
+opts_mapping = {
+    "backup_be_name" :    ("",  "backup-be-name"),
+    "be_name" :           ("",  "be-name"),
+    "deny_new_be" :       ("",  "deny-new-be"),
+    "no_backup_be" :      ("",  "no-backup-be"),
+    "be_activate" :       ("",  "no-be-activate"),
+    "require_backup_be" : ("",  "require-backup-be"),
+    "require_new_be" :    ("",  "require-new-be"),
+
+    "concurrency" :       ("C", "concurrency"),
+
+    "force" :             ("f", ""),
+
+    "li_ignore_all" :     ("I", ""),
+    "li_ignore_list" :    ("i", ""),
+    "li_md_only" :        ("",  "linked-md-only"),
+
+    "li_pkg_updates" :    ("",  "no-pkg-updates"),
+
+    "li_parent_sync" :    ("",  "no-parent-sync"),
+
+    "li_props" :          ("",  "prop-linked"),
+
+    "li_target_all" :     ("a", ""),
+    "li_target_list" :    ("l", ""),
+
+    "li_name" :           ("l",  ""),
+
+    "accept" :            ("",  "accept"),
+    "show_licenses" :     ("",  "licenses"),
+
+    "omit_headers" :      ("H",  ""),
+
+    "update_index" :      ("",  "no-index"),
+
+    "refresh_catalogs" :  ("",  "no-refresh"),
+
+    "reject_pats" :       ("",  "reject"),
+
+    "verbose" :           ("v",  ""),
+
+    "quiet" :             ("q",  ""),
+
+    "parsable_version" :  ("",  "parsable"),
+
+    "noexecute" :         ("n",  ""),
+
+    "origins" :           ("g",  ""),
+
+    "stage" :             ("",  "stage"),
+
+    "allow_relink" :      ("",  "allow-relink"),
+    "attach_child" :      ("c",  ""),
+    "attach_parent" :     ("p",  ""),
+
+    "list_available" :    ("a",  ""),
+    "list_masked" :       ("m",  ""),
+    "list_all_items" :    ("a",  ""),
+    "output_format" :     ("F",  "output-format"),
+
+    "tagged" :            ("",  "tagged"),
+
+    # These options are used in set-mediator and unset-mediator but
+    # the long options are only valid in set_mediator (as per the previous
+    # implementation). However, the long options are not documented in the
+    # manpage for set-mediator either, so I think we're good.
+    "med_implementation" : ("I",  "implementation"),
+    "med_version" :        ("V",  "version"),
+
+    "list_installed_newest" : ("a",  ""),
+    "list_all" :              ("f",  ""),
+    "list_newest" :           ("n",  ""),
+    "summary" :               ("s",  ""),
+    "list_upgradable" :       ("u",  ""),
+
+    "ctlfd" :                 ("",  "ctlfd"),
+    "progfd" :                ("",  "progfd"),
+
+    "list_installed" :        ("i",  ""),
+}
+
+#
 # cmds dictionary is used to dispatch subcommands.  The format of this
 # dictionary is:
 #
-#       "subcommand-name" : (
-#               subcommand-cb,
-#               subcommand-opts-table,
-#               arguments-allowed
-#       )
+#       "subcommand-name" : subcommand-cb
 #
 #       subcommand-cb: the callback function invoked for this subcommand
-#       subcommand-opts-table: an arguments options table that is passed to
-#               the common options processing function misc.opts_parse().
-#               if None then misc.opts_parse() is not invoked.
-#
-#       arguments-allowed (optional): the number of additional arguments
-#               allowed to this function, which is also passed to
-#               misc.opts_parse()
 #
 # placeholders in this lookup table for image-create, help and version
 # which don't have dedicated methods
 #
 cmds = {
-    "add-property-value"    : (property_add_value, None),
-    "attach-linked"         : (attach_linked, opts_attach_linked, 2),
-    "avoid"                 : (avoid, None),
-    "audit-linked"          : (audit_linked, opts_audit_linked),
-    "authority"             : (publisher_list, None),
-    "change-facet"          : (change_facet, opts_install, -1),
-    "change-variant"        : (change_variant, opts_install, -1),
-    "contents"              : (list_contents, None),
-    "detach-linked"         : (detach_linked, opts_detach_linked),
-    "facet"                 : (facet_list, None),
-    "fix"                   : (fix_image, None),
-    "freeze"                : (freeze, None),
-    "help"                  : (None, None),
-    "history"               : (history_list, None),
-    "image-create"          : (None, None),
-    "info"                  : (info, None),
-    "install"               : (install, opts_install, -1),
-    "list"                  : (list_inventory, opts_list_inventory, -1),
-    "list-linked"           : (list_linked, opts_list_linked),
-    "mediator"              : (list_mediators, opts_list_mediator, -1),
-    "property"              : (property_list, None),
-    "property-linked"       : (list_property_linked,
-                                  opts_list_property_linked, -1),
-    "pubcheck-linked"       : (pubcheck_linked, []),
-    "publisher"             : (publisher_list, None),
-    "purge-history"         : (history_purge, None),
-    "rebuild-index"         : (rebuild_index, None),
-    "refresh"               : (publisher_refresh, None),
-    "remote"                : (remote, opts_remote, 0),
-    "remove-property-value" : (property_remove_value, None),
-    "revert"                : (revert, opts_revert, -1),
-    "search"                : (search, None),
-    "set-authority"         : (publisher_set, None),
-    "set-mediator"          : (set_mediator, opts_set_mediator, -1),
-    "set-property"          : (property_set, None),
-    "set-property-linked"   : (set_property_linked,
-                                  opts_set_property_linked, -1),
-    "set-publisher"         : (publisher_set, None),
-    "sync-linked"           : (sync_linked, opts_sync_linked),
-    "unavoid"               : (unavoid, None),
-    "unfreeze"              : (unfreeze, None),
-    "uninstall"             : (uninstall, opts_uninstall, -1),
-    "unset-authority"       : (publisher_unset, None),
-    "unset-property"        : (property_unset, None),
-    "update-format"         : (update_format, None),
-    "unset-mediator"        : (unset_mediator, opts_unset_mediator, -1),
-    "unset-publisher"       : (publisher_unset, None),
-    "update"                : (update, opts_update, -1),
-    "update-format"         : (update_format, None),
-    "variant"               : (variant_list, None),
-    "verify"                : (verify_image, None),
-    "version"               : (None, None),
+    "add-property-value"    : [property_add_value],
+    "attach-linked"         : [attach_linked, 2],
+    "avoid"                 : [avoid],
+    "audit-linked"          : [audit_linked, 0],
+    "authority"             : [publisher_list],
+    "change-facet"          : [change_facet],
+    "change-variant"        : [change_variant],
+    "contents"              : [list_contents],
+    "detach-linked"         : [detach_linked, 0],
+    "facet"                 : [list_facet],
+    "fix"                   : [fix_image],
+    "freeze"                : [freeze],
+    "help"                  : [None],
+    "history"               : [history_list],
+    "image-create"          : [None],
+    "info"                  : [info],
+    "install"               : [install],
+    "list"                  : [list_inventory],
+    "list-linked"           : [list_linked, 0],
+    "mediator"              : [list_mediators],
+    "property"              : [property_list],
+    "property-linked"       : [list_property_linked],
+    "pubcheck-linked"       : [pubcheck_linked, 0],
+    "publisher"             : [publisher_list],
+    "purge-history"         : [history_purge],
+    "rebuild-index"         : [rebuild_index],
+    "refresh"               : [publisher_refresh],
+    "remote"                : [remote, 0],
+    "remove-property-value" : [property_remove_value],
+    "revert"                : [revert],
+    "search"                : [search],
+    "set-authority"         : [publisher_set],
+    "set-mediator"          : [set_mediator],
+    "set-property"          : [property_set],
+    "set-property-linked"   : [set_property_linked],
+    "set-publisher"         : [publisher_set],
+    "sync-linked"           : [sync_linked, 0],
+    "unavoid"               : [unavoid],
+    "unfreeze"              : [unfreeze],
+    "uninstall"             : [uninstall],
+    "unset-authority"       : [publisher_unset],
+    "unset-property"        : [property_unset],
+    "unset-mediator"        : [unset_mediator],
+    "unset-publisher"       : [publisher_unset],
+    "update"                : [update],
+    "update-format"         : [update_format],
+    "variant"               : [list_variant],
+    "verify"                : [verify_image],
+    "version"               : [None],
 }
 
+# These tables are an addendum to the the pkg_op_opts/opts_* lists in
+# modules/client/options.py. They contain all the options for functions which
+# are not represented in options.py but go through common option processing.
+# This list should get shortened and eventually removed by moving more/all
+# functions out of client.py.
+
+def opts_cb_remote(api_inst, opts, opts_new):
+        options.opts_cb_fd("ctlfd", api_inst, opts, opts_new)
+        options.opts_cb_fd("progfd", api_inst, opts, opts_new)
+
+        # move progfd from opts_new into a global
+        global_settings.client_output_progfd = opts_new["progfd"]
+        del opts_new["progfd"]
+
+opts_remote = [
+    opts_cb_remote,
+    ("ctlfd",                None),
+    ("progfd",               None),
+]
+
+def opts_cb_varcet(api_inst, opts, opts_new):
+        if opts_new["list_all_items"] and opts_new["list_installed"]:
+                raise api_errors.InvalidOptionError(
+                    api_errors.InvalidOptionError.INCOMPAT,
+                    ["list_all_items", "list_installed"])
+
+opts_list_varcet = \
+    options.opts_table_no_headers + \
+    [
+    opts_cb_varcet,
+    ("list_all_items",          False),
+    ("list_installed",          False),
+    ("output_format",           None)
+]
+
+opts_list_facet = \
+    opts_list_varcet + \
+    [
+    ("list_masked",             False),
+]
+
+opts_list_variant = \
+    opts_list_varcet + \
+    [
+    ("verbose",      False)
+]
+
+opts_list_mediator = \
+    options.opts_table_no_headers + \
+    [
+    ("list_available",      False),
+    ("output_format",       None)
+]
+opts_unset_mediator = \
+    options.opts_table_beopts + \
+    options.opts_table_no_index + \
+    options.opts_table_nqv + \
+    options.opts_table_parsable + \
+    [
+    ("med_implementation",   False),
+    ("med_version",          False)
+]
+
+cmd_opts = {
+    "facet"             : opts_list_facet,
+    "mediator"          : opts_list_mediator,
+    "unset-mediator"    : opts_unset_mediator,
+    "remote"            : opts_remote,
+    "variant"           : opts_list_variant,
+}
+
+
 def main_func():
         global_settings.client_name = PKG_CLIENT_NAME
 
@@ -6460,28 +6178,100 @@
         img = api_inst.img
 
         # Find subcommand and execute operation.
-        pargs_limit = 0
         func = cmds[subcommand][0]
-        opts_cmd = cmds[subcommand][1]
-        if len(cmds[subcommand]) > 2:
-                pargs_limit = cmds[subcommand][2]
-        try:
-                if opts_cmd == None:
+        pargs_limit = None
+        if len(cmds[subcommand]) > 1:
+                pargs_limit = cmds[subcommand][1]
+
+        pkg_timer.record("client startup", logger=logger)
+
+        # Get the available options for the requested operation to create the
+        # getopt parsing strings.
+        valid_opts = options.get_pkg_opts(subcommand, add_table=cmd_opts)
+        if not valid_opts:
+                # if there are no options for an op, it has its own processing
+                try:
                         return func(api_inst, pargs)
-
-                opts, pargs = misc.opts_parse(subcommand, api_inst, pargs,
-                    opts_cmd, pargs_limit, usage)
-
-                # Reset the progress tracker here, because we may have
-                # to switch to a different tracker due to the options parse.
-                _api_inst.progresstracker = get_tracker()
-
-                pkg_timer.record("client startup", logger=logger)
-                return func(op=subcommand, api_inst=api_inst,
-                    pargs=pargs, **opts)
-
-        except getopt.GetoptError, e:
-                usage(_("illegal option -- %s") % e.opt, cmd=subcommand)
+                except getopt.GetoptError, e:
+                        usage(_("illegal option -- %s") % e.opt,
+                            cmd=subcommand)
+
+        try:
+                # Parse CLI arguments into dictionary containing corresponding
+                # options and values.
+                opt_dict, pargs = misc.opts_parse(subcommand, pargs, valid_opts,
+                    opts_mapping, usage)
+
+                if pargs_limit is not None and len(pargs) > pargs_limit:
+                        usage(_("illegal argument -- %s") % pargs[pargs_limit],
+                            cmd=subcommand)
+
+                opts = options.opts_assemble(subcommand, api_inst, opt_dict,
+                    add_table=cmd_opts, cwd=orig_cwd)
+
+        except api_errors.InvalidOptionError, e:
+
+                # We can't use the string representation of the exception since
+                # it references internal option names. We substitute the CLI
+                # options and create a new exception to make sure the messages
+                # are correct.
+
+                # Convert the internal options to CLI options. We make sure that
+                # when there is a short and a long version for the same option
+                # we print both to avoid confusion.
+                def get_cli_opt(option):
+                        try:
+                                s, l = opts_mapping[option]
+                                if l and not s:
+                                        return "--%s" % l
+                                elif s and not l:
+                                        return "-%s" % s
+                                else:
+                                        return "-%s/--%s" % (s, l)
+                        except KeyError:
+                                # ignore if we can't find a match
+                                # (happens for repeated arguments)
+                                return option
+
+                cli_opts = []
+                opt_def = []
+
+                for o in e.options:
+                        cli_opts.append(get_cli_opt(o))
+
+                        # collect the default value (see comment below)
+                        opt_def.append(options.get_pkg_opts_defaults(subcommand,
+                            o, add_table=cmd_opts))
+
+                # Prepare for headache:
+                # If we have an option 'b' which is set to True by default it
+                # will be toggled to False if the users specifies the according
+                # option on the CLI.
+                # If we now have an option 'a' which requires option 'b' to be
+                # set, we can't say "'a' requires 'b'" because the user can only
+                # specify 'not b'. So the correct message would be:
+                # "'a' is incompatible with 'not b'".
+                # We can get there by just changing the type of the exception
+                # for all cases where the default value of one of the options is
+                # True.
+                if e.err_type == api_errors.InvalidOptionError.REQUIRED:
+                        if len(opt_def) == 2 and (opt_def[0] or opt_def[1]):
+                                e.err_type = \
+                                    api_errors.InvalidOptionError.INCOMPAT
+
+                # This new exception will have the CLI options, so can be passed
+                # directly to usage().
+                new_e = api_errors.InvalidOptionError(err_type=e.err_type,
+                    options=cli_opts, msg=e.msg)
+
+                usage(str(new_e), cmd=subcommand)
+
+        # Reset the progress tracker here, because we may have
+        # to switch to a different tracker due to the options parse.
+        _api_inst.progresstracker = get_tracker()
+
+        return func(op=subcommand, api_inst=api_inst,
+            pargs=pargs, **opts)
 
 #
 # Establish a specific exit status which means: "python barfed an exception"
@@ -6607,7 +6397,8 @@
                 __ret = handle_errors(_wrapper, non_wrap_print=False)
                 s = ""
                 if __ret == 99:
-                        s += _("\n%s%s") % (__e, traceback_str)
+                        s += _("\n%(err)s%(stacktrace)s") % \
+                        {"err": __e, "stacktrace": traceback_str}
 
                 s += _("\n\nDespite the error while indexing, the operation "
                     "has completed successfuly.")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/depot-config.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,668 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+import errno
+import getopt
+import gettext
+import locale
+import logging
+import os
+import re
+import shutil
+import socket
+import sys
+import traceback
+import warnings
+
+from mako.template import Template
+from mako.lookup import TemplateLookup
+
+import pkg
+import pkg.client.api_errors as apx
+import pkg.catalog
+import pkg.config as cfg
+import pkg.misc as misc
+import pkg.portable as portable
+import pkg.p5i as p5i
+import pkg.server.repository as sr
+import pkg.smf as smf
+
+from pkg.client import global_settings
+from pkg.client.debugvalues import DebugValues
+from pkg.misc import msg, PipeError
+
+logger = global_settings.logger
+
+# exit codes
+EXIT_OK      = 0
+EXIT_OOPS    = 1
+EXIT_BADOPT  = 2
+
+DEPOT_HTTP_TEMPLATE = "depot_httpd.conf.mako"
+DEPOT_FRAGMENT_TEMPLATE = "depot.conf.mako"
+
+DEPOT_HTTP_FILENAME = "depot_httpd.conf"
+DEPOT_FRAGMENT_FILENAME= "depot.conf"
+
+DEPOT_PUB_FILENAME = "index.html"
+DEPOT_HTDOCS_DIRNAME = "htdocs"
+
+DEPOT_VERSIONS_DIRNAME = ["versions", "0"]
+DEPOT_PUB_DIRNAME = ["publisher", "1"]
+
+DEPOT_CACHE_FILENAME = "depot.cache"
+
+KNOWN_SERVER_TYPES = ["apache2"]
+
+PKG_SERVER_SVC = "svc:/application/pkg/server"
+
+# static string with our versions response
+DEPOT_FRAGMENT_VERSIONS_STR = """\
+pkg-server %s
+publisher 0 1
+versions 0
+catalog 1
+file 1
+manifest 0
+""" % pkg.VERSION
+
+# versions response used when we provide search capability
+DEPOT_VERSIONS_STR = """%sadmin 0
+search 0 1
+""" % DEPOT_FRAGMENT_VERSIONS_STR
+
+DEPOT_USER = "pkg5srv"
+DEPOT_GROUP = "pkg5srv"
+
+class DepotException(Exception):
+        def __unicode__(self):
+        # To workaround python issues 6108 and 2517, this provides a
+        # a standard wrapper for this class' exceptions so that they
+        # have a chance of being stringified correctly.
+                return str(self)
+
+
+def error(text, cmd=None):
+        """Emit an error message prefixed by the command name """
+
+        if cmd:
+                text = "%s: %s" % (cmd, text)
+                pkg_cmd = "pkg.depot-config "
+        else:
+                pkg_cmd = "pkg.depot-config: "
+
+                # If we get passed something like an Exception, we can convert
+                # it down to a string.
+                text = str(text)
+
+        # If the message starts with whitespace, assume that it should come
+        # *before* the command-name prefix.
+        text_nows = text.lstrip()
+        ws = text[:len(text) - len(text_nows)]
+
+        # This has to be a constant value as we can't reliably get our actual
+        # program name on all platforms.
+        logger.error(ws + pkg_cmd + text_nows)
+
+def usage(usage_error=None, cmd=None, retcode=EXIT_BADOPT):
+        """Emit a usage message and optionally prefix it with a more
+        specific error message.  Causes program to exit.
+        """
+
+        if usage_error:
+                error(usage_error, cmd=cmd)
+        msg(_("""\
+Usage:
+        pkg.depot-config ( -d repository_dir | -S ) -r runtime_dir
+                [-c cache_dir] [-s cache_size] [-p port] [-h hostname]
+                [-l logs_dir] [-T template_dir] [-A]
+                [-t server_type] ( [-F] [-P server_prefix] )
+"""))
+        sys.exit(retcode)
+
+def _chown_dir(dir):
+        """Sets ownership for the given directory to pkg5srv:pkg5srv"""
+
+        uid = portable.get_user_by_name(DEPOT_USER, None, False)
+        gid = portable.get_group_by_name(DEPOT_GROUP, None, False)
+        try:
+                os.chown(dir, uid, gid)
+        except OSError, err:
+                if not os.environ.get("PKG5_TEST_ENV", None):
+                        raise DepotException(_("Unable to chown %(dir)s to "
+                            "%(user)s:%(group)s: %(err)s") %
+                            {"dir": dir, "user": DEPOT_USER,
+                            "group": DEPOT_GROUP, "err": err})
+
+def _get_publishers(root):
+        """Given a repository root, return the list of available publishers,
+        along with the default publisher/prefix."""
+
+        try:
+                # we don't set writable_root, as we don't want to take the hit
+                # on potentially building an index here.
+                repository = sr.Repository(root=root, read_only=True)
+
+                if repository.version != 4:
+                        raise DepotException(
+                            _("pkg.depot-config only supports v4 repositories"))
+        except Exception, e:
+                raise DepotException(e)
+
+        all_pubs = [pub.prefix for pub in repository.get_publishers()]
+        try:
+                default_pub = repository.cfg.get_property("publisher", "prefix")
+        except cfg.UnknownPropertyError:
+                default_pub = None
+        return all_pubs, default_pub
+
+def _write_httpd_conf(pubs, default_pubs, runtime_dir, log_dir, template_dir,
+        cache_dir, cache_size, host, port, sroot,
+        fragment=False, allow_refresh=False):
+        """Writes the webserver configuration for the depot.
+
+        pubs            repository and publisher information, a list in the form
+                        [(publisher_prefix, repo_dir, repo_prefix), ... ]
+        default_pubs    default publishers, per repository, a list in the form
+                        [(default_publisher_prefix, repo_dir, repo_prefix) ... ]
+
+        runtime_dir     where we write httpd.conf files
+        log_dir         where Apache should write its log files
+        template_dir    where we find our Mako templates
+        cache_dir       where Apache should write its cache and wsgi search idx
+        cache_size      how large our cache can grow
+        host            our hostname, needed to set ServerName properly
+        port            the port on which Apache should listen
+        sroot           the prefix into the server namespace,
+                        ignored if fragment==False
+        fragment        True if we should only write a file to drop into conf.d/
+                        (i.e. a partial server configuration)
+
+        allow_refresh   True if we allow the 'refresh' or 'refresh-indexes'
+                        admin/0 operations
+
+        The URI namespace we create on the web server looks like this:
+
+        <sroot>/<repo_prefix>/<publisher>/<file, catalog etc.>/<version>/
+        <sroot>/<repo_prefix>/<file, catalog etc.>/<version>/
+
+        'sroot' is only used when the Apache server is serving other content
+        and we want to separate pkg(5) resources from the other resources
+        provided.
+
+        'repo_prefix' exists so that we can disambiguate between multiple
+        repositories that provide the same publisher.
+        """
+
+        try:
+                # check our hostname
+                socket.getaddrinfo(host, None)
+
+                # Apache needs IPv6 addresses wrapped in square brackets
+                if ":" in host:
+                        host = "[%s]" % host
+
+                # check our directories
+                dirs = [runtime_dir]
+                if not fragment:
+                        dirs.append(log_dir)
+                if cache_dir:
+                        dirs.append(cache_dir)
+                for dir in dirs + [template_dir]:
+                        if os.path.exists(dir) and not os.path.isdir(dir):
+                                raise DepotException(
+                                    _("%s is not a directory") % dir)
+
+                for dir in dirs:
+                        misc.makedirs(dir)
+
+                # check our port
+                if not fragment:
+                        try:
+                                num = int(port)
+                                if num <= 0 or num >= 65535:
+                                        raise DepotException(
+                                            _("invalid port: %s") % port)
+                        except ValueError:
+                                raise DepotException(_("invalid port: %s") %
+                                    port)
+
+                # check our cache size
+                try:
+                        num = int(cache_size)
+                        if num < 0:
+                                raise DepotException(_("invalid cache size: "
+                                   "%s") % num)
+                except ValueError:
+                        raise DepotException(_("invalid cache size: %s") %
+                            cache_size)
+
+                httpd_conf_template_path = os.path.join(template_dir,
+                    DEPOT_HTTP_TEMPLATE)
+                fragment_conf_template_path = os.path.join(template_dir,
+                    DEPOT_FRAGMENT_TEMPLATE)
+
+                # we're disabling unicode here because we want Mako to
+                # passthrough any filesystem path names, whatever the
+                # original encoding.
+                conf_lookup = TemplateLookup(directories=[template_dir])
+                if fragment:
+                        conf_template = Template(
+                            filename=fragment_conf_template_path,
+                            disable_unicode=True, lookup=conf_lookup)
+                        conf_path = os.path.join(runtime_dir,
+                            DEPOT_FRAGMENT_FILENAME)
+                else:
+                        conf_template = Template(
+                            filename=httpd_conf_template_path,
+                            disable_unicode=True, lookup=conf_lookup)
+                        conf_path = os.path.join(runtime_dir,
+                            DEPOT_HTTP_FILENAME)
+
+                conf_text = conf_template.render(
+                    pubs=pubs,
+                    default_pubs=default_pubs,
+                    log_dir=log_dir,
+                    cache_dir=cache_dir,
+                    cache_size=cache_size,
+                    runtime_dir=runtime_dir,
+                    template_dir=template_dir,
+                    ipv6_addr="::1",
+                    host=host,
+                    port=port,
+                    sroot=sroot,
+                    allow_refresh=allow_refresh
+                )
+
+                with file(conf_path, "wb") as conf_file:
+                        conf_file.write(conf_text)
+
+        except socket.gaierror, err:
+                raise DepotException(
+                    _("Unable to write Apache configuration: %(host)s: "
+                    "%(err)s") % locals())
+        except (OSError, IOError, EnvironmentError, apx.ApiException), err:
+                traceback.print_exc(err)
+                raise DepotException(
+                    _("Unable to write depot_httpd.conf: %s") % err)
+
+def _write_versions_response(htdocs_path, fragment=False):
+        """Writes a static versions/0 response for the Apache depot."""
+
+        try:
+                versions_path = os.path.join(htdocs_path,
+                    *DEPOT_VERSIONS_DIRNAME)
+                misc.makedirs(versions_path)
+
+                with file(os.path.join(versions_path, "index.html"), "w") as \
+                    versions_file:
+                        versions_file.write(
+                            fragment and DEPOT_FRAGMENT_VERSIONS_STR or
+                            DEPOT_VERSIONS_STR)
+
+                versions_file.close()
+        except (OSError, apx.ApiException), err:
+                raise DepotException(
+                    _("Unable to write versions response: %s") % err)
+
+def _write_publisher_response(pubs, htdocs_path, repo_prefix):
+        """Writes a static publisher/0 response for the depot."""
+        try:
+                # convert our list of strings to a list of Publishers
+                pub_objs = [pkg.client.publisher.Publisher(pub) for pub in pubs]
+
+                # write individual reponses for the publishers
+                for pub in pub_objs:
+                        pub_path = os.path.join(htdocs_path,
+                            os.path.sep.join(
+                               [repo_prefix, pub.prefix] + DEPOT_PUB_DIRNAME))
+                        misc.makedirs(pub_path)
+                        with file(os.path.join(pub_path, "index.html"), "w") as\
+                            pub_file:
+                                p5i.write(pub_file, [pub])
+
+                # write a response that contains all publishers
+                pub_path = os.path.join(htdocs_path,
+                    os.path.sep.join([repo_prefix] + DEPOT_PUB_DIRNAME))
+                os.makedirs(pub_path)
+                with file(os.path.join(pub_path, "index.html"), "w") as \
+                    pub_file:
+                        p5i.write(pub_file, pub_objs)
+
+        except (OSError, apx.ApiException), err:
+                raise DepotException(
+                    _("Unable to write publisher response: %s") % err)
+
+def cleanup_conf(runtime_dir=None):
+        """Destroys an old configuration."""
+        try:
+                shutil.rmtree(runtime_dir, ignore_errors=True)
+        except OSError, err:
+                raise DepotException(
+                    _("Unable to cleanup old configuration: %s") % err)
+
+def refresh_conf(repo_info, log_dir, host, port, runtime_dir,
+            template_dir, cache_dir, cache_size, sroot, fragment=False,
+            allow_refresh=False):
+        """Creates a new configuration for the depot."""
+        try:
+                ret = EXIT_OK
+                cleanup_conf(runtime_dir=runtime_dir)
+                if not repo_info:
+                        raise DepotException(_("no repositories found"))
+
+                htdocs_path = os.path.join(runtime_dir, DEPOT_HTDOCS_DIRNAME,
+                    sroot)
+                misc.makedirs(htdocs_path)
+
+                # pubs and default_pubs are lists of tuples of the form:
+                # (publisher prefix, repository root dir, repository prefix)
+                pubs = []
+                default_pubs = []
+
+                repo_prefixes = [prefix for root, prefix in repo_info]
+                errors = []
+
+                # Query each repository for its publisher information.
+                for (repo_root, repo_prefix) in repo_info:
+                        try:
+                                publishers, default_pub = \
+                                    _get_publishers(repo_root)
+                                for pub in publishers:
+                                        pubs.append(
+                                            (pub, repo_root,
+                                            repo_prefix))
+                                default_pubs.append((default_pub,
+                                    repo_root, repo_prefix))
+
+                        except DepotException, err:
+                                errors.append(str(err))
+                if errors:
+                        raise DepotException(_("Unable to get publisher "
+                            "information: %s") % "\n".join(errors))
+
+                # Write the publisher/0 response for each repository
+                pubs_by_repo = {}
+                for pub_prefix, repo_root, repo_prefix in pubs:
+                        pubs_by_repo.setdefault(repo_prefix, []).append(
+                            pub_prefix)
+                for repo_prefix in pubs_by_repo:
+                        _write_publisher_response(
+                            pubs_by_repo[repo_prefix], htdocs_path, repo_prefix)
+
+                _write_httpd_conf(pubs, default_pubs, runtime_dir, log_dir,
+                    template_dir, cache_dir, cache_size, host, port, sroot,
+                    fragment=fragment, allow_refresh=allow_refresh)
+                _write_versions_response(htdocs_path, fragment=fragment)
+                # If we're writing a configuration fragment, then the web server
+                # is probably not running as DEPOT_USER:DEPOT_GROUP
+                if not fragment:
+                        _chown_dir(runtime_dir)
+                        _chown_dir(cache_dir)
+                else:
+                        msg(_("Created %s/depot.conf") % runtime_dir)
+        except (DepotException, OSError, apx.ApiException), err:
+                error(err)
+                ret = EXIT_OOPS
+        return ret
+
+def get_smf_repo_info():
+        """Return a list of repo_info from the online instances of pkg/server
+        which are marked as pkg/standalone = False and pkg/readonly = True."""
+
+        smf_instances = smf.check_fmris(None, "%s:*" % PKG_SERVER_SVC)
+        repo_info = []
+        for fmri in smf_instances:
+                repo_prefix = fmri.split(":")[-1]
+                repo_root = smf.get_prop(fmri, "pkg/inst_root")
+                state = smf.get_prop(fmri, "restarter/state")
+                readonly = smf.get_prop(fmri, "pkg/readonly")
+                standalone = smf.get_prop(fmri, "pkg/standalone")
+
+                if (state == "online" and
+                    readonly == "true" and
+                    standalone == "false"):
+                        repo_info.append((repo_root,
+                            _affix_slash(repo_prefix)))
+        if not repo_info:
+                raise DepotException(_(
+                    "No online, readonly, non-standalone instances of "
+                    "%s found.") % PKG_SERVER_SVC)
+        return repo_info
+
+def _check_unique_repo_properties(repo_info):
+        """Determine whether the repository root, and supplied prefixes are
+        unique.  The prefixes allow two or more repositories that both contain
+        the same publisher to be differentiated in the Apache configuration, so
+        that requests are routed to the correct repository."""
+
+        prefixes = set()
+        roots = set()
+        errors = []
+        for root, prefix in repo_info:
+                if prefix in prefixes:
+                        errors.append(_("instance %s already exists") % prefix)
+                prefixes.add(prefix)
+                if root in roots:
+                        errors.append(_("repo_root %s already exists") % root)
+                roots.add(root)
+        if errors:
+                raise DepotException("\n".join(errors))
+        return True
+
+def _affix_slash(str):
+        val = str.lstrip("/").rstrip("/")
+        if "/" in str:
+                raise DepotException(_("cannot use '/' chars in prefixes"))
+        # An RE that matches valid SMF instance names works for prefixes
+        if not re.match(r"^([A-Za-z][_A-Za-z0-9.-]*,)?[A-Za-z][_A-Za-z0-9-]*$",
+            str):
+                raise DepotException(_("%s is not a valid prefix"))
+        return "%s/" % val
+
+def main_func():
+
+        # some sensible defaults
+        host = "0.0.0.0"
+        # the port we listen on
+        port = None
+        # a list of (repo_dir, repo_prefix) tuples
+        repo_info = []
+        # the path where we store indexes and disk caches
+        cache_dir = None
+        # our maximum cache size, in megabytes
+        cache_size = 0
+        # whether we're writing a full httpd.conf, or just a fragment
+        fragment = False
+        # an optional url-prefix, used to separate pkg5 services from the rest
+        # of the webserver url namespace, only used when running in fragment
+        # mode, otherwise we assume we're the only service running on this
+        # web server instance, and control the entire server URL namespace.
+        sroot = ""
+        # the path where our Mako templates and wsgi scripts are stored
+        template_dir = "/etc/pkg/depot"
+        # a volatile directory used at runtime for storing state
+        runtime_dir = None
+        # where logs are written
+        log_dir = "/var/log/pkg/depot"
+        # whether we should pull configuration from
+        # svc:/application/pkg/server instances
+        use_smf_instances = False
+        # whether we allow admin/0 operations to rebuild the index
+        allow_refresh = False
+        # the current server_type
+        server_type = "apache2"
+
+        try:
+                opts, pargs = getopt.getopt(sys.argv[1:],
+                    "Ac:d:Fh:l:P:p:r:Ss:t:T:?", ["help", "debug="])
+                for opt, arg in opts:
+                        if opt == "--help":
+                                usage()
+                        elif opt == "-h":
+                                host = arg
+                        elif opt == "-c":
+                                cache_dir = arg
+                        elif opt == "-s":
+                                cache_size = arg
+                        elif opt == "-l":
+                                log_dir = arg
+                        elif opt == "-p":
+                                port = arg
+                        elif opt == "-r":
+                                runtime_dir = arg
+                        elif opt == "-T":
+                                template_dir = arg
+                        elif opt == "-t":
+                                server_type = arg
+                        elif opt == "-d":
+                                if "=" not in arg:
+                                        usage(_("-d arguments must be in the "
+                                            "form <prefix>=<repo path>"))
+                                prefix, root = arg.split("=", 1)
+                                repo_info.append((root, _affix_slash(prefix)))
+                        elif opt == "-P":
+                                sroot = _affix_slash(arg)
+                        elif opt == "-F":
+                                fragment = True
+                        elif opt == "-S":
+                                use_smf_instances = True
+                        elif opt == "-A":
+                                allow_refresh = True
+                        elif opt == "--debug":
+                                try:
+                                        key, value = arg.split("=", 1)
+                                except (AttributeError, ValueError):
+                                        usage(
+                                            _("%(opt)s takes argument of form "
+                                            "name=value, not %(arg)s") % {
+                                            "opt": opt, "arg": arg })
+                                DebugValues.set_value(key, value)
+                        else:
+                                usage("unknown option %s" % opt)
+
+        except getopt.GetoptError, e:
+                usage(_("illegal global option -- %s") % e.opt)
+
+        if not runtime_dir:
+                usage(_("required runtime dir option -r missing."))
+
+        # we need a cache_dir to store the search indexes
+        if not cache_dir and not fragment:
+                usage(_("cache_dir option -c is required if -F is not used."))
+
+        if not fragment and not port:
+                usage(_("required port option -p missing."))
+
+        if not use_smf_instances and not repo_info:
+                usage(_("at least one -d option is required if -S is "
+                    "not used."))
+
+        if repo_info and use_smf_instances:
+                usage(_("cannot use -d and -S together."))
+
+        if fragment and port:
+                usage(_("cannot use -F and -p together."))
+
+        if fragment and allow_refresh:
+                usage(_("cannot use -F and -A together."))
+
+        if sroot and not fragment:
+                usage(_("cannot use -P without -F."))
+
+        if use_smf_instances:
+                try:
+                        repo_info = get_smf_repo_info()
+                except DepotException, e:
+                        error(e)
+
+        # In the future we may produce configuration for different
+        # HTTP servers. For now, we only support "apache2"
+        if server_type not in KNOWN_SERVER_TYPES:
+                usage(_("unknown server type %(type)s. "
+                    "Known types are: %(known)s") %
+                    {"type": server_type,
+                    "known": ", ".join(KNOWN_SERVER_TYPES)})
+
+        _check_unique_repo_properties(repo_info)
+
+        ret = refresh_conf(repo_info, log_dir, host, port, runtime_dir,
+            template_dir, cache_dir, cache_size, sroot, fragment=fragment,
+            allow_refresh=allow_refresh)
+        return ret
+
+#
+# Establish a specific exit status which means: "python barfed an exception"
+# so that we can more easily detect these in testing of the CLI commands.
+#
+def handle_errors(func, *args, **kwargs):
+        """Catch exceptions raised by the main program function and then print
+        a message and/or exit with an appropriate return code.
+        """
+
+        traceback_str = misc.get_traceback_message()
+
+        try:
+                # Out of memory errors can be raised as EnvironmentErrors with
+                # an errno of ENOMEM, so in order to handle those exceptions
+                # with other errnos, we nest this try block and have the outer
+                # one handle the other instances.
+                try:
+                        __ret = func(*args, **kwargs)
+                except (MemoryError, EnvironmentError), __e:
+                        if isinstance(__e, EnvironmentError) and \
+                            __e.errno != errno.ENOMEM:
+                                raise
+                        error("\n" + misc.out_of_memory())
+                        __ret = EXIT_OOPS
+        except SystemExit, __e:
+                raise __e
+        except (PipeError, KeyboardInterrupt):
+                # Don't display any messages here to prevent possible further
+                # broken pipe (EPIPE) errors.
+                __ret = EXIT_OOPS
+        except:
+                traceback.print_exc()
+                error(traceback_str)
+                __ret = 99
+        return __ret
+
+
+if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+
+        # Make all warnings be errors.
+        warnings.simplefilter('error')
+
+        __retval = handle_errors(main_func)
+        try:
+                logging.shutdown()
+        except IOError:
+                # Ignore python's spurious pipe problems.
+                pass
+        sys.exit(__retval)
--- a/src/depot.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/depot.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates.  All rights reserved.
+# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 # pkg.depotd - package repository daemon
@@ -129,8 +129,8 @@
            [-t socket_timeout] [--cfg] [--content-root]
            [--disable-ops op[/1][,...]] [--debug feature_list]
            [--image-root dir] [--log-access dest] [--log-errors dest]
-           [--mirror] [--nasty] [--proxy-base url] [--readonly]
-           [--ssl-cert-file] [--ssl-dialog] [--ssl-key-file]
+           [--mirror] [--nasty] [--nasty-sleep] [--proxy-base url]
+           [--readonly] [--ssl-cert-file] [--ssl-dialog] [--ssl-key-file]
            [--sort-file-max-size size] [--writable-root dir]
 
         -a address      The IP address on which to listen for connections.  The
@@ -184,6 +184,8 @@
                         clients, and generally be hostile.  The option
                         takes a value (1 to 100) for how nasty the server
                         should be.
+        --nasty-sleep   In nasty mode (see --nasty), how many seconds to
+                        randomly sleep when a random sleep occurs.
         --proxy-base    The url to use as the base for generating internal
                         redirects and content.
         --readonly      Read-only operation; modifying operations disallowed.
@@ -236,10 +238,9 @@
         rebuild = False
         reindex = False
         nasty = False
-        nasty_value = 0
 
         # Track initial configuration values.
-        ivalues = { "pkg": {} }
+        ivalues = { "pkg": {}, "nasty": {} }
         if "PKG_REPO" in os.environ:
                 ivalues["pkg"]["inst_root"] = os.environ["PKG_REPO"]
 
@@ -265,10 +266,10 @@
                 long_opts = ["add-content", "cfg=", "cfg-file=",
                     "content-root=", "debug=", "disable-ops=", "exit-ready",
                     "help", "image-root=", "log-access=", "log-errors=",
-                    "llmirror", "mirror", "nasty=", "proxy-base=", "readonly",
-                    "rebuild", "refresh-index", "set-property=",
-                    "ssl-cert-file=", "ssl-dialog=", "ssl-key-file=",
-                    "sort-file-max-size=", "writable-root="]
+                    "llmirror", "mirror", "nasty=", "nasty-sleep=",
+                    "proxy-base=", "readonly", "rebuild", "refresh-index",
+                    "set-property=", "ssl-cert-file=", "ssl-dialog=",
+                    "ssl-key-file=", "sort-file-max-size=", "writable-root="]
 
                 opts, pargs = getopt.getopt(sys.argv[1:], "a:d:np:s:t:?",
                     long_opts)
@@ -348,18 +349,18 @@
                                 ivalues["pkg"]["ll_mirror"] = True
                                 ivalues["pkg"]["readonly"] = True
                         elif opt == "--nasty":
-                                value_err = None
-                                try:
-                                        nasty_value = int(arg)
-                                except ValueError, e:
-                                        value_err = e
-
-                                if value_err or (nasty_value > 100 or
-                                    nasty_value < 1):
+                                # ValueError is caught by caller.
+                                nasty_value = int(arg)
+                                if (nasty_value > 100 or nasty_value < 1):
                                         raise OptionError, "Invalid value " \
                                             "for nasty option.\n Please " \
                                             "choose a value between 1 and 100."
                                 nasty = True
+                                ivalues["nasty"]["nasty_level"] = nasty_value
+                        elif opt == "--nasty-sleep":
+                                # ValueError is caught by caller.
+                                sleep_value = int(arg)
+                                ivalues["nasty"]["nasty_sleep"] = sleep_value
                         elif opt == "--proxy-base":
                                 # Attempt to decompose the url provided into
                                 # its base parts.  This is done so we can
@@ -690,7 +691,6 @@
                 else:
                         # Redirect the server to the decrypted key file.
                         ssl_key_file = "/dev/fd/%d" % key_data.fileno()
-                        key_data.close()
 
         # Setup our global configuration.
         gconf = {
@@ -838,7 +838,6 @@
         # Next, initialize depot.
         if nasty:
                 depot = ds.NastyDepotHTTP(repo, dconf)
-                depot.set_nasty(nasty_value)
         else:
                 depot = ds.DepotHTTP(repo, dconf)
 
--- a/src/man/ja_JP/packagemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/packagemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH packagemanager 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH packagemanager 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 packagemanager \- Image Packaging System の GUI 
 .SH 形式
@@ -11,9 +11,9 @@
 
 .LP
 .nf
-/usr/bin/packagemanager [-hiRu] [--help]
-    [--info-install \fIfile\fR] [--update-all]
-    [--image-dir \fIdir\fR]
+/usr/bin/packagemanager [-h | --help]
+    [-i | --info-install \fIfile\fR] [-U | --update-all]
+    [-R | --image-dir \fIdir\fR]
 .fi
 
 .LP
@@ -27,7 +27,7 @@
 \fBpackagemanager\fR は、\fB pkg\fR(5) (Image Packaging System ソフトウェア) のグラフィカルユーザーインタフェースです。
 .sp
 .LP
-パッケージマネージャーを使用すると、次の作業を実行できます。
+パッケージマネージャーを使用すると、次のタスクを実行できます。
 .RS +4
 .TP
 .ie t \(bu
@@ -52,12 +52,16 @@
 .SH オプション
 .sp
 .LP
-次のオプションを指定できます。
+サポートしているオプションは、次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-h\fR または \fB--help\fR\fR
+\fB\fB-h\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -68,18 +72,26 @@
 .ne 2
 .mk
 .na
-\fB\fB-i\fR または \fB--info-install\fR \fI file\fR\fR
+\fB\fB-i\fR \fIfile\fR\fR
+.ad
+.br
+.na
+\fB\fB--info-install\fR \fIfile\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fB\&.p5i\fR ファイルを指定して、\fBpackagemanager\fR を Web インストールモードで実行できます。\fIfile\fR の接尾辞は \fB\&.p5i\fR である必要があります。
+\fB\&.p5i\fR ファイルを指定して、\fBpackagemanager\fR を Web インストールモードで実行します。\fIfile\fR の接尾辞は \fB\&.p5i\fR である必要があります。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-R\fR または \fB--image-dir\fR \fI dir\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
+.ad
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -90,7 +102,11 @@
 .ne 2
 .mk
 .na
-\fB\fB-U\fR または \fB--update-all\fR\fR
+\fB\fB-U\fR\fR
+.ad
+.br
+.na
+\fB\fB--update-all\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -161,16 +177,16 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
 .na
 \fB\fB0\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
-すべて正常に動作しました。
+すべてが動作しました。
 .RE
 
 .sp
@@ -179,20 +195,20 @@
 .na
 \fB\fB1\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .SH ファイル
@@ -259,7 +275,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpm-updatemanager\fR(1), \fBpkg\fR(1), \fB pkg\fR(5)
+\fBpm-updatemanager\fR(1), \fBpkg\fR(1), \fBpkg\fR(5)
 .sp
 .LP
 パッケージマネージャーのオンラインヘルプ
--- a/src/man/ja_JP/pkg.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkg.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkg 1 "2011 年 8 月 30 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkg 1 "2012 年 6 月 26 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkg \- Image Packaging System 取得クライアント
 .SH 形式
@@ -11,31 +11,34 @@
 
 .LP
 .nf
-/usr/bin/pkg refresh [--full] [\fIpublisher\fR ...]
+/usr/bin/pkg refresh [-q] [--full] [\fIpublisher\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg install [-nvq] [-g \fIpath_or_uri\fR ...] [--accept]
-    [--licenses] [--no-be-activate] [--no-index] [--no-refresh]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg install [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
+    [--accept] [--licenses] [--no-be-activate] [--no-index]
+    [--no-refresh] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     [--reject \fIpkg_fmri_pattern\fR ...] \fIpkg_fmri_pattern\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg uninstall [-nvq] [--no-be-activate] [--no-index]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg uninstall [-nvq] [-C \fIn\fR] [--no-be-activate]
+    [--no-index] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fIpkg_fmri_pattern\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg update [-fnvq] [-g \fIpath_or_uri\fR ...] [--accept]
-    [--licenses] [--no-be-activate] [--no-index] [--no-refresh]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg update [-fnvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
+    [--accept] [--licenses] [--no-be-activate] [--no-index]
+    [--no-refresh] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     [--reject \fIpkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...]
 .fi
@@ -56,7 +59,7 @@
 .nf
 /usr/bin/pkg contents [-Hmr] [-a \fIattribute\fR=\fIpattern\fR ...]
     [-g \fIpath_or_uri\fR ...] [-o \fIattribute\fR ...] [-s \fIsort_key\fR]
-    [-t \fIaction_type\fR ...] [\fIpkg_fmri_pattern\fR ...]
+    [-t \fIaction_name\fR ...] [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
@@ -72,13 +75,15 @@
 
 .LP
 .nf
-/usr/bin/pkg fix [--accept] [--licenses] [\fIpkg_fmri_pattern\fR ...]
+/usr/bin/pkg fix [--accept] [--licenses]
+    [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkg revert [-nv] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     (--tagged \fItag-name\fR ... | \fIpath-to-file\fR ...)
 .fi
@@ -92,7 +97,8 @@
 .nf
 usr/bin/pkg set-mediator [-nv] [-I \fIimplementation\fR]
     [-V \fIversion\fR] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fImediator\fR ...
 .fi
@@ -100,37 +106,40 @@
 .LP
 .nf
 /usr/bin/pkg unset-mediator [-nvIV] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fImediator\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg variant [-H] [\fIvariant_spec\fR]
+/usr/bin/pkg variant [-H] [variant.\fIvariant_name\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg change-variant [-nvq] [-g \fIpath_or_uri\fR ...]
+/usr/bin/pkg change-variant [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
     [--accept] [--licenses] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
-    \fIvariant_spec\fR=\fIinstance\fR ...
+    \fIvariant_name\fR=\fIvalue\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg facet [-H] [\fIfacet_spec\fR]
+/usr/bin/pkg facet [-H] [\fIfacet_name\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg change-facet [-nvq] [-g \fIpath_or_uri\fR ...]
+/usr/bin/pkg change-facet [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
     [--accept] [--licenses] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
-    [--deny-new-be | --require-new-be] [--be-name \fIname\fR] 
-    \fIfacet_spec\fR=[True|False|None] ...
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
+    [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
+    \fIfacet_name\fR=[True|False|None] ...
 .fi
 
 .LP
@@ -180,7 +189,7 @@
 
 .LP
 .nf
-/usr/bin/pkg publisher [-HPn] [\fIpublisher\fR ...]
+/usr/bin/pkg publisher [-HPn] [-F \fIformat\fR] [\fIpublisher\fR ...]
 .fi
 
 .LP
@@ -190,18 +199,32 @@
     [-G \fIorigin_to_remove\fR | --remove-origin \fIorigin_to_remove\fR ...]
     [-m \fImirror_to_add\fR | --add-mirror \fImirror_to_add\fR ...]
     [-M \fImirror_to_remove\fR | --remove-mirror \fImirror_to_remove\fR ...]
-    [-p \fIrepo_uri\fR] [--enable] [--disable] [--no-refresh]
-    [--reset-uuid] [--non-sticky] [--sticky]
-    [--search-after \fIpublisher\fR] [--search-before \fIpublisher\fR]
-    [--search-first]
+    [--enable] [--disable] [--no-refresh] [--reset-uuid]
+    [--non-sticky] [--sticky] [--search-after \fIpublisher\fR]
+    [--search-before \fIpublisher\fR] [--search-first]
     [--approve-ca-cert \fIpath_to_CA\fR]
     [--revoke-ca-cert \fIhash_of_CA_to_remove\fR]
     [--unset-ca-cert \fIhash_of_CA_to_remove\fR]
     [--set-property \fIname_of_property\fR=\fIvalue\fR]
     [--add-property-value \fIname_of_property\fR=\fIvalue_to_add\fR]
     [--remove-property-value \fIname_of_property\fR=\fIvalue_to_remove\fR]
-    [--unset-property \fIname_of_property_to_delete\fR]
-    [\fIpublisher\fR]
+    [--unset-property \fIname_of_property_to_delete\fR] 
+    [--proxy \fIproxy_to_use\fR] \fIpublisher\fR
+.fi
+
+.LP
+.nf
+/usr/bin/pkg set-publisher -p \fIrepo_uri\fR [-Ped]
+    [-k \fIssl_key\fR] [-c \fIssl_cert\fR] [--non-sticky] [--sticky]
+    [--search-after \fIpublisher\fR] [--search-before \fIpublisher\fR
+    [--search-first] [--approve-ca-cert \fIpath_to_CA\fR]
+    [--revoke-ca-cert \fIhash_of_CA_to_remove\fR]
+    [--unset-ca-cert \fIhash_of_CA_to_remove\fR]
+    [--set-property \fIname_of_property\fR=\fIvalue\fR]
+    [--add-property-value \fIname_of_property\fR=\fIvalue_to_add\fR]
+    [--remove-property-value \fIname_of_property\fR=\fIvalue_to_remove\fR]
+    [--unset-property \fIname_of_property_to_delete\fR] 
+    [--proxy \fIproxy_to_use\fR] [\fIpublisher\fR]
 .fi
 
 .LP
@@ -211,7 +234,7 @@
 
 .LP
 .nf
-/usr/bin/pkg history [-Hl] [-t [\fItime\fR | \fItime\fR-\fItime\fR],...]
+/usr/bin/pkg history [-HNl] [-t [\fItime\fR | \fItime\fR-\fItime\fR],...]
     [-o \fIcolumn\fR,...] [-n \fInumber\fR]
 .fi
 
@@ -244,11 +267,12 @@
 .nf
 /usr/bin/pkg image-create [-FPUfz] [--force]
     [--full | --partial | --user] [--zone]
-    [-k \fIssl_key\fR] [-c \fIssl_cert\fR]
-    [--no-refresh] [--variant \fIvariant_spec\fR=\fIinstance\fR ...]
+    [-k \fIssl_key\fR] [-c \fIssl_cert\fR] [--no-refresh]
+    [--variant \fIvariant_name\fR=\fIvalue\fR ...]
     [-g \fIpath_or_uri\fR | --origin \fIpath_or_uri\fR ...]
     [-m \fIuri\fR | --mirror \fIuri\fR ...]
-    [--facet \fIfacet_spec\fR=(True|False) ...]
+    [--set-property \fIname_of_property\fR=\fIvalue\fR]
+    [--facet \fIfacet_name\fR=(True|False) ...]
     [(-p | --publisher) [\fIname\fR=]\fIrepo_uri\fR] \fIdir\fR
 .fi
 
@@ -264,105 +288,305 @@
 リポジトリは、クライアントがパッケージの内容 (プログラムやドキュメントなど、パッケージの内部に含まれるファイル) とメタデータ (パッケージの名前や説明など、パッケージについての情報) を公開および取得できる場所です。たとえば、\fBexample.org\fR という名前のパブリッシャーは、\fBhttp://example.org/repository\fR という URI にリポジトリを配置することができます。
 .sp
 .LP
-\fBpkg\fR では、パッケージをアンインストールしたり、(利用可能なパッケージの一覧などの) パブリッシャーメタデータを更新したり、イメージにインストールされたパッケージを検証したり、イメージからさまざまなトークンを照会したりすることもできます。これらのクエリーは \fBpkg\fR(5) リポジトリで構成することもできます。
+\fBpkg\fR では、パッケージをアンインストールしたり、(利用可能なパッケージの一覧などの) パブリッシャーメタデータをリフレッシュしたり、イメージにインストールされたパッケージを検証したり、イメージからさまざまなトークンを照会したりすることもできます。これらのクエリーは \fBpkg\fR(5) リポジトリで構成することもできます。
 .sp
 .LP
 イメージには 3 つの種類があります。完全なシステムを提供できるフルイメージ、フルイメージ (親イメージ) にリンクされるがそれ自身では完全なシステムを提供しない部分イメージ、およびユーザーイメージです。
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-R\fR \fIdir\fR\fR
 .ad
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fIdir\fR をルートとするイメージを操作します。ディレクトリが指定されなかったか、または環境に基づいて決定される場合、デフォルトは / です。詳細は、「環境変数」のセクションを参照してください。
+.RE
+
+.SH サブコマンド
+.sp
+.LP
+サポートされているサブコマンドは次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg refresh\fR [\fB-q\fR] [\fB- -full\fR] [\fIpublisher\fR ...]\fR
+.ad
 .sp .6
 .RS 4n
-\fIdir\fR をルートとするイメージを操作します。ディレクトリが指定、または環境に基づいて判別されなかった場合のデフォルトは / です。詳細は、環境変数に関する節を参照してください。
+クライアントの利用可能パッケージの一覧およびすべての発行元の発行元メタデータを更新します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+クライアントの利用可能パッケージの一覧、および指定された発行元の発行元メタデータのみを更新します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+リクエストされた操作の実行中、進捗状況メッセージを表示しません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--full\fR\fR
+.ad
+.sp .6
+.RS 4n
+増分更新を試みる代わりにすべての発行元メタデータを強制的に完全取得し、操作中に使用されるすべてのプロキシでキャッシュデータを無視するようにリクエストします。このオプションはトラブルシューティング目的に用意されており、通常時は使用しないでください。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR または \fB-?\fR\fR
+\fB\fBpkg install\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [\fB--no-backup-be\fR | \fB--require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fI name\fR] [\fB--reject\fR \fIpkg_fmri_pattern\fR ...] \fI pkg_fmri_pattern\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-使用方法に関するメッセージを表示します。
+指定されたパッケージをインストールし、イメージにインストールされたパッケージで許容されている \fIpkg_fmri_pattern\fR と一致する最新バージョンにパッケージを更新します。パッケージの最新バージョンを明示的に要求するには、\fIpkg_fmri_pattern\fR のバージョン部分に \fBlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
+.sp
+パッケージは、発行元検索順およびスティッキネスに基づいて選択されます。検索順およびスティッキネスについては、\fBpkg publisher\fR および \fBpkg set-publisher\fR コマンドを参照してください。\fIpkg_fmri_pattern \fR が発行元を指定しない場合、一致するパッケージを提供する最初の発行元がインストール元として使用されます。該当する発行元がこのイメージ内にインストール可能なパッケージのバージョンを提供しない場合、インストール操作は失敗します。このイメージにインストール可能なパッケージのバージョンを提供する発行元を確認するには、\fBpkg list -a\fR コマンドを使用します。
+.sp
+複数の \fIpkg_fmri_pattern\fR が指定され、かつ指定されたパッケージのいずれかをこのイメージにインストールできない場合、指定されたパッケージは一切インストールされません。
+.sp
+インストールプロセスの間に、一部の設定ファイルの名前変更または置換が行われる場合があります。どのファイルを保持するかをパッケージシステムが決定する方法と、パッケージ操作中にファイルが保持されるしくみについては、\fBpkg\fR(5) のマニュアルページのファイルアクションに関する項目を参照してください。
+.sp
+パッケージが回避リストにある場合は、インストールすると回避リストから削除されます。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパッケージリポジトリまたはアーカイブを、パッケージデータの取得元になるイメージ内のソースリストに一時的に追加します。クライアント SSL 証明書が必要なリポジトリは、このオプションとともに使用できません。このオプションは複数回指定できます。
+.sp
+どのバージョンのパッケージを使用するかを決定するときは、イメージ内に構成されているが、指定された \fIpath_or_uri\fR ソースに見つからない発行元が優先されます。インストールするパッケージのバージョンが、イメージ内で構成されている発行元および \fIpath_or_uri\fR ソースから提供されている場合、クライアントはそのパッケージの内容を \fIpath_or_uri \fR ソースから取得します。インストールまたは更新のあとに、発行元によって提供され、イメージ内で構成されていないパッケージがある場合は、起点なしでイメージ構成に追加されます。イメージ内で構成されている発行元を表示するには、\fBpkg publisher\fR コマンドを使用します。
 .RE
 
-.SH サブコマンド
-.sp
-.LP
-次のサブコマンドがサポートされています。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージの変更は行わずに試しに操作を実行します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrefresh [\fB--full\fR] [\fIpublisher \fR ...]\fR\fR
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+リクエストされた操作の実行中に詳細な進捗状況メッセージを出力し、詳細な計画情報 (ファセット、メディエータ、バリアントの変更など) を表示します。このオプションを複数回指定して、表示される計画情報の量を増やすことができます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-q\fR\fR
 .ad
 .sp .6
 .RS 4n
-指定されたパブリッシャーごとに、クライアントの利用可能パッケージの一覧およびパブリッシャーメタデータを更新します。パブリッシャーを指定しない場合、すべてのパブリッシャーを対象に操作が実行されます。
-.sp
-\fB--full\fR を指定すると、増分更新を試みる代わりにすべてのパブリッシャーメタデータを強制的に完全取得し、操作中に使用されるすべてのプロキシでキャッシュデータを無視するように要求します。このオプションはトラブルシューティング目的に用意されており、通常時は使用しないでください。
+リクエストされた操作の実行中、進捗状況メッセージを表示しません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-C\fR \fIn\fR\fR
+.ad
+.sp .6
+.RS 4n
+同時に更新する子イメージの数を指定します。子イメージ (通常はゾーン) 内への再帰時に、最大 \fIn\fR 個の子イメージを同時に更新します。更新する子イメージのデフォルト数は、1 です。\fIn\fR が 0 または負数の場合は、すべての子イメージが同時に更新されます。「環境変数」セクションの「\fBPKG_CONCURRENCY\fR」も参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--accept\fR\fR
+.ad
+.sp .6
+.RS 4n
+更新またはインストールされるパッケージのライセンス条項に同意することを示します。このオプションを指定しないと、パッケージのライセンスに同意が必要になった場合、インストール操作は失敗します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--licenses\fR\fR
+.ad
+.sp .6
+.RS 4n
+この操作の一環としてインストールまたは更新されるパッケージのすべてのライセンスを表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinstall [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] [\fB--reject\fR \fI pkg_fmri_pattern\fR ...] \fIpkg_fmri_pattern\fR ... \fR\fR
+\fB\fB--no-backup-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+バックアップブート環境を作成しません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-be-activate\fR\fR
+.ad
+.sp .6
+.RS 4n
+ブート環境が作成される場合に、それを次回ブート時にアクティブなブート環境として設定しません。詳細は、\fBbeadm\fR(1M) のマニュアルページを参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+操作が正常に完了したあとに検索インデックスを更新しません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
 .ad
 .sp .6
 .RS 4n
-パッケージをインストールし、イメージにインストールされたパッケージで許容されている \fIpkg_fmri_pattern\fR と一致する最新バージョンにパッケージを更新します。パッケージの最新バージョンを明示的に要求するには、\fIpkg_fmri_pattern\fR のバージョン部分に \fBlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
-.sp
-インストールプロセスの間に、一部の設定ファイルの名前変更または置換が行われる場合があります。どのファイルを保持するかをパッケージシステムが決定する方法と、パッケージ操作中にファイルが保持されるしくみについては、\fBpkg\fR(5) のファイルアクションに関する項目を参照してください。
-.sp
-パッケージが回避リストにある場合は、インストールすると回避リストから削除されます。
-.sp
-\fB-g\fR を指定すると、パッケージデータの取得元である指定のパッケージリポジトリまたはアーカイブが、イメージ内のソースのリストに一時的に追加されます。指定されたソースからのパッケージが、イメージ内に構成されているパブリッシャーからも入手できる場合でも、クライアントは指定されたソースのみからパッケージの内容を取得します。どのバージョンのパッケージを使用するかを決定するときは、イメージ内に構成されているけれども指定されたソースに見つからないパブリッシャーが優先されます。インストールまたは更新のあとに、パブリッシャーによって提供され、イメージ内に見つからないパッケージがある場合は、起点なしでイメージ構成に追加されます。このオプションは複数回指定できます。
-.sp
-\fB-n\fR を指定すると、パッケージの変更は行わずに試しに操作を実行します。
-.sp
-\fB-q\fR を指定すると、要求された操作の実行中、進捗状況メッセージを表示しません。
-.sp
-\fB-v\fR を指定すると、要求された操作の実行中に詳細な進捗状況メッセージを出力し、詳細な計画情報 (ファセット、メディエータ、バリアントの変更など) を表示します。このオプションを複数回指定して、表示される計画情報の量を増やすことができます。
-.sp
-\fB--accept\fR は、更新またはインストールされるパッケージのライセンス条項に同意することを示します。このオプションを指定しないと、パッケージのライセンスに同意が必要になった場合、インストール操作は失敗します。
-.sp
-\fB--licenses\fR を指定すると、この操作の一環としてインストールまたは更新されるパッケージのすべてのライセンスを表示します。
-.sp
-\fB--no-backup-be\fR を指定すると、バックアップブート環境を作成しません。
-.sp
-\fB--no-be-activate\fR を指定すると、ブート環境が作成される場合に、それを次回ブート時にアクティブ BE として設定しません。詳細は、\fBbeadm\fR(1M) を参照してください。
-.sp
-\fB--no-index\fR を指定すると、操作が正常に完了したあとに検索インデックスを更新しません。
-.sp
-\fB--no-refresh\fR を指定すると、入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージのパブリッシャー用のリポジトリへのアクセスを試みません。
-.sp
-\fB--backup-be-name \fR を指定すると、指定された引数を使用して、作成されたバックアップブート環境に名前を付けます。\fB--backup-be-name\fR を使用すると \fB--require-backup-be\fR が暗黙的に指定されます。\fBbeadm\fR(1M) も参照してください。
-.sp
-\fB--be-name\fR を指定すると、新たに作成されたブート環境の名前を、指定された引数になるように変更します。\fB--be-name\fR を使用すると \fB- -require-new-be\fR が暗黙的に指定されます。\fBbeadm\fR(1M) も参照してください。
-.sp
-\fB--require-backup-be \fR を指定すると、新しいブート環境が作成されない場合に常にバックアップブート環境を作成します。このオプションを指定しないと、イメージポリシーに基づいてバックアップブート環境が作成されます。バックアップブート環境がいつ自動的に作成されるかについての説明は、次の「イメージプロパティー」の \fBbe-policy\fR を参照してください。
-.sp
-\fB--require-new-be\fR を指定すると、常に新しいブート環境を作成します。このオプションを指定しないと、イメージポリシーに基づいてブート環境が作成されます。ブート環境がいつ自動的に作成されるかについての説明は、次の「イメージプロパティー」の \fBbe-policy\fR を参照してください。このオプションを \fB--require-backup-be\fR と組み合わせることはできません。
-.sp
-\fB--deny-new-be\fR を指定すると、新しいブート環境を作成しません。新しいブート環境が必要な場合、この操作は実行されません。
-.sp
-\fB--reject\fR を指定すると、指定されたパターンと一致する名前を持つパッケージはインストールされません。一致するパッケージがすでにインストールされている場合、それらはこの操作の一環として削除されます。グループ依存関係のターゲットである拒否対象パッケージは回避リストに登録されます。
+入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージの発行元用のリポジトリへのアクセスを試みません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--backup-be-name\fR \fIname\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された引数を使って、作成されたバックアップブート環境に名前を付けます。\fB--backup-be-name\fR を使用すると \fB--require-backup-be\fR が暗黙的に指定されます。\fBbeadm\fR(1M) のマニュアルページも参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--be-name\fR \fIname\fR\fR
+.ad
+.sp .6
+.RS 4n
+新たに作成されたブート環境の名前を、指定された引数になるように変更します。\fB--be-name\fR の使用は、暗黙的に \fB--require-new-be\fR を示します。\fBbeadm\fR(1M) のマニュアルページも参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--require-backup-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+新しいブート環境が作成されない場合に、常にバックアップブート環境を作成します。このオプションを指定しないと、イメージポリシーに基づいてバックアップブート環境が作成されます。バックアップブート環境がいつ自動的に作成されるかについての説明は、次の「イメージプロパティー」の \fBbe-policy\fR を参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--require-new-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+常に新しいブート環境を作成します。このオプションを指定しないと、イメージポリシーに基づいてブート環境が作成されます。ブート環境がいつ自動的に作成されるかについての説明は、次の「イメージプロパティー」の \fBbe-policy\fR を参照してください。このオプションを \fB--require-backup-be\fR と組み合わせることはできません。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBuninstall [\fB-nvq\fR] [\fB--no-be-activate \fR] [\fB--no-index\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI pkg_fmri_pattern\fR ...\fR\fR
+\fB\fB--deny-new-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+新しいブート環境を作成しません。新しいブート環境が必要な場合、この操作は実行されません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--reject\fR \fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパターンと一致する名前を持つパッケージはインストールされません。一致するパッケージがすでにインストールされている場合、それらはこの操作の一環として削除されます。グループ依存関係のターゲットである拒否対象パッケージは回避リストに登録されます。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg uninstall\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIpkg_fmri_pattern\fR ... \fR
 .ad
 .sp .6
 .RS 4n
@@ -370,55 +594,82 @@
 .sp
 パッケージがグループ依存関係の対象である場合、パッケージをアンインストールするとそのパッケージは回避リストに登録されます。後述する \fBavoid\fR サブコマンドを参照してください。
 .sp
-その他すべてのオプションの使用法および効果については、前述した \fBinstall\fR コマンドを参照してください。
+オプションの説明については、前述の \fBinstall\fR コマンドを参照してください。
+.sp
+コマンド出力で、新しいブート環境が作成されたことを示すメッセージに注意してください。新しいブート環境を作成してアクティブにすると、それが次回リブート時のデフォルトのブート環境になります。ブート環境の管理については、\fB beadm\fR(1M) のマニュアルページを参照してください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBupdate [\fB-fnvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] [\fB--reject\fR \fI pkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg update\fR [\fB-fnvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [\fB--no-backup-be\fR | \fB--require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fI name\fR] [\fB--reject\fR \fIpkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-引数を指定しないか、または提供されたパターンの 1 つがアスタリスク (*) である場合、現在のイメージ内のすべてのインストール済みパッケージを、インストール済みパッケージおよびパブリッシャー構成によってシステムに適用される制約で許可される最新のバージョンに更新します。パッケージの最新バージョンを明示的に要求するには、\fBpkg_fmri_pattern\fR のバージョン部分に \fIlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
-.sp
-\fIpkg_fmri_pattern\fR を指定した場合、\fBupdate\fR は、\fIpkg_fmri_pattern\fR に一致するインストール済みパッケージを、パターンによって許可され、さらにインストール済みパッケージおよびパブリッシャー構成によってシステムに課せられる制約によって許可される、最新のバージョンに置き換えます。すでにインストールされているものより古い、または新しいバージョンを指定することで、特定のパッケージのインプレースダウングレードまたはアップグレードを実行できます。パッケージの名前変更または廃止の境界をまたがった特定パッケージの更新はサポートされていません。
-.sp
-保持される設定ファイルのうち、\fBupdate\fR によってダウングレードされるパッケージの一部であり、元のバージョンがインストールされたあとに変更されたファイルは、拡張子 \fB\&.update\fR を使用して名前が変更されます。どのファイルを保持するかをパッケージシステムが決定する方法と、パッケージのアップグレード中にこれらのファイルが保持されるしくみについては、\fBpkg\fR(5) のファイルアクションに関する項目を参照してください。
-.sp
-\fB-f\fR オプションを指定すると、すべてのインストール済みパッケージを更新するときにクライアントに対する最新状態チェックを実行しません。
-.sp
-その他すべてのオプションの使用法および効果については、前述した \fBinstall\fR コマンドを参照してください。
+現在のイメージ内のすべてのインストール済みパッケージを、インストール済みパッケージと発行元構成によりシステムに適用される制約で許可される最新のバージョンに更新します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージにインストール済みの、指定されたパッケージのみを更新します。指定された \fIpkg_fmri_pattern\fR パターンの 1 つがアスタリスク (*) である場合、現在のイメージ内のすべてのインストール済みパッケージを前述のとおりに更新します。
+.sp
+パッケージの最新バージョンを明示的に要求するには、\fIpkg_fmri_pattern\fR のバージョン部分に \fBlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
+.sp
+すでにインストールされているものより古い、または新しいバージョンを指定することで、特定のパッケージのインプレースダウングレードまたはアップグレードを実行できます。パッケージの名前変更または廃止の境界をまたがった特定パッケージの更新はサポートされていません。
+.sp
+保持される構成ファイルのうち、ダウングレードされるパッケージの一部であり、元のバージョンがインストールされたあとに変更されたファイルは、拡張子 \fB\&.update\fR を使用して名前が変更されます。どのファイルを保持するかをパッケージシステムが決定する方法と、パッケージアップグレード中にファイルが保持されるしくみについては、\fBpkg\fR(5) のマニュアルページのファイルアクションに関する項目を参照してください。
+.sp
+複数の \fIpkg_fmri_pattern\fR が指定され、かつ指定されたパッケージのいずれかをこのイメージに更新できない場合、指定されたパッケージは一切更新されません。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBlist [\fB-Hafnsuv\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--no-refresh\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fB-f\fR\fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内のパッケージの一覧を、状態やその他の情報を含めて表示します。デフォルトでは、異なるアーキテクチャーまたはゾーンタイプのパッケージバリアントは除外されます。通常の出力は 3 列形式です。
+すべてのインストール済みパッケージを更新するときにクライアントに対する最新状態チェックを実行しません。
+.RE
+
+その他のすべてのオプションについては、前述の \fBinstall\fR コマンドを参照してください。
+.sp
+コマンド出力で、新しいブート環境が作成されたことを示すメッセージに注意してください。新しいブート環境を作成してアクティブにすると、それが次回、\fB--no-be-activate\fR オプションを指定しない場合のリブート時のデフォルトブート環境になります。ブート環境の管理については、\fBbeadm\fR(1M) のマニュアルページを参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg list\fR [\fB-Hafnsuv\fR] [\fB-g\fR \fIpath_or_uri\fR ...] [\fB--no-refresh \fR] [\fIpkg_fmri_pattern\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+バージョンやインストール状態などの情報を含む、現在のイメージ内のインストール済みの全パッケージのリストを表示します。デフォルトでは、異なるアーキテクチャーまたはゾーンタイプのパッケージバリアントは除外されます。通常の出力は 3 列形式です。
 .sp
 .in +2
 .nf
-NAME (PUBLISHER)            VERSION           IFO
-system/core-os              0.5.11-0.169      i--
-x11/wm/fvwm (fvwm.org)      2.6.1-3           i--
+NAME (PUBLISHER)       VERSION                IFO
+system/core-os         0.5.11-0.175.0.0.0.2.1 i--
+x11/wm/fvwm (fvwm.org) 2.6.5                  i--
 .fi
 .in -2
 
-最初の列にはパッケージの名前が表示されます。パッケージのインストール元 (または、インストールされていない場合は提供元) であるパブリッシャーがパブリッシャー検索順で先頭でない場合、パッケージ名のあとに一覧表示されるパブリッシャー名は括弧で囲まれています。2 番目の列にはパッケージのリリースバージョンとブランチバージョンが表示されます。リリースバージョンとブランチバージョンについては、\fBpkg\fR(5) を参照してください。
+最初の列にはパッケージの名前が表示されます。パッケージのインストール元 (または、インストールされていない場合は提供元) であるパブリッシャーがパブリッシャー検索順で先頭でない場合、パッケージ名のあとに一覧表示されるパブリッシャー名は括弧で囲まれています。2 番目の列にはパッケージのリリースバージョンとブランチバージョンが表示されます。リリースバージョンとブランチバージョンについて、およびバリアントについては、\fBpkg\fR(5) のマニュアルページを参照してください。
 .sp
 .LP
-最後の列には、パッケージの状態を示す一連のフラグが表示されます。
+最後の列には、パッケージのステータスを示す一連のフラグが表示されます。
 .RS +4
 .TP
 .ie t \(bu
 .el o
-\fBI\fR 列の \fBi\fR は、パッケージがインストールされていることを示します。.
+\fBI\fR 列の \fBi\fR は、パッケージがインストールされていることを示します。
 .RE
 .RS +4
 .TP
@@ -432,68 +683,292 @@
 .el o
 \fBO\fR 列の \fBo\fR は、パッケージが廃止されていることを示します。\fBO\fR 列の \fBr\fR は、パッケージの名前が変更されたことを示します (廃止の形態の 1 つです)。
 .RE
-\fB-H\fR を指定すると、一覧表示からヘッダーを省略します。
-.sp
-\fB-a\fR を指定すると、インストール済みパッケージと、インストールのために入手可能なパッケージの最新バージョンを一覧表示します。インストール済みの incorporation によって、またイメージのバリアントによって許可されている場合、そのパッケージはインストールのために入手可能であるとみなされます。1 つ以上のパターンを指定した場合、指定されたパターンに一致し、インストール済みの incorporation およびイメージのバリアントによって許可されている最新バージョンが一覧表示されます。\fB-a\fR を指定しない場合、インストール済みパッケージのみを一覧表示します。
-.sp
-\fB-f\fR および \fB-a\fR を指定した場合、incorporation の制約またはインストール状態に関係なく、すべてのバリアントについてすべてのパッケージのすべてのバージョンを一覧表示します。これらのオプションを使用するとき、パッケージの最新バージョンを明示的に一覧表示するには、\fIpkg_fmri_pattern\fR のバージョン部分に \fBlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
-.sp
-\fB-g\fR を指定すると、指定されたパッケージリポジトリまたはアーカイブを、操作のためのパッケージデータのソースとして使用します。このオプションは複数回指定できます。\fB-n\fR を指定しない場合、\fB-g\fR を使用すると \fB-a\fR が暗黙的に指定されます。
-.sp
-\fB-n\fR を指定すると、インストール状態に関係なく、すべての既知のパッケージの最新バージョンを表示します。
-.sp
-\fB-s\fR を指定すると、パッケージ名と要約を示す 1 行の短縮形式を表示します。このオプションは \fB-a\fR、\fB-n\fR、\fB-u\fR、または \fB-v\fR とともに使用できます。
-.sp
-\fB-u\fR を指定すると、新しいバージョンが入手可能なパッケージのみを一覧表示します。このオプションは \fB-g\fR とともに使用できません。
-.sp
-\fB-v\fR を指定すると、パブリッシャーと完全バージョンを含む、フルパッケージ FMRI をすべて最初の列に表示します (VERSION 列は消えます)。このオプションは \fB-a\fR、\fB-n\fR、または \fB-u\fR とともに使用できます。
-.sp
-\fB--no-refresh\fR を指定すると、入手可能なパッケージの最新リストを取得するために、イメージのパブリッシャー用のリポジトリへのアクセスを試みません。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定したパッケージのみを一覧表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+インストール済みパッケージと、インストールのために入手可能なパッケージの最新バージョンを一覧表示します。インストール済みの incorporation によって、またイメージのバリアントによって許可されている場合、そのパッケージはインストールのために入手可能であるとみなされます。1 つ以上のパターンを指定した場合、指定されたパターンに一致し、インストール済みの incorporation およびイメージのバリアントによって許可されている最新バージョンが一覧表示されます。\fB-a\fR を指定しない場合、インストール済みパッケージのみを一覧表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-af\fR\fR
+.ad
+.sp .6
+.RS 4n
+incorporation の制約またはインストール状態に関係なく、すべてのバリアントについてすべてのパッケージのすべてのバージョンを一覧表示します。これらのオプションを使用するとき、パッケージの最新バージョンを明示的に一覧表示するには、\fIpkg_fmri_pattern\fR のバージョン部分に \fBlatest\fR を使用します。たとえば、\fBvim@latest\fR のように指定します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパッケージリポジトリまたはアーカイブを、操作のためのパッケージデータのソースとして使用します。クライアント SSL 証明書が必要なリポジトリは、このオプションとともに使用できません。このオプションは複数回指定できます。\fB-n\fR を指定しない場合、\fB-g\fR を使用すると \fB-a\fR が暗黙的に指定されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+インストール状態に関係なく、すべての既知のパッケージの最新バージョンを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージ名とサマリーを示す 1 行の短縮形式を表示します。このオプションは \fB-a\fR、\fB-n\fR、\fB-u\fR、または \fB-v\fR とともに使用できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-u\fR\fR
+.ad
+.sp .6
+.RS 4n
+新しいバージョンが入手可能なパッケージのみを一覧表示します。このオプションは \fB-g\fR とともに使用できません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+発行元と完全バージョンを含む、フルパッケージ FMRI をすべて最初の列に表示します (VERSION 列は消えます)。このオプションは \fB-a\fR、\fB-n\fR、または \fB-u\fR とともに使用できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージの発行元用のリポジトリへのアクセスを試みません。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg info\fR [\fB-lr\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--license\fR] [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージにインストールされているすべてのパッケージについての情報を、人間が判読できる形式で表示します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定したパッケージの情報のみを表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinfo [\fB-lr\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--license\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパッケージリポジトリまたはアーカイブを、操作のためのパッケージデータのソースとして使用します。クライアント SSL 証明書が必要なリポジトリは、このオプションとともに使用できません。このオプションは複数回指定できます。\fB-g\fR を使用すると \fB-r\fR が暗黙的に指定されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
+.ad
+.sp .6
+.RS 4n
+インストール済みのパッケージの情報だけを表示します。これはデフォルトです。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
 .ad
 .sp .6
 .RS 4n
-パッケージについての情報を人間が判読できる形式で表示します。複数の FMRI パターンを指定できます。パターンを指定しない場合、イメージ内のすべてのインストール済みパッケージについての情報を表示します。
-.sp
-\fB-g\fR を指定すると、指定されたパッケージリポジトリまたはアーカイブを、操作のためのパッケージデータのソースとして使用します。このオプションは複数回指定できます。\fB-g\fR を使用すると \fB-r\fR が暗黙的に指定されます。
-.sp
-\fB-l\fR を指定すると、インストール済みパッケージの情報のみを表示します。これはデフォルトです。
-.sp
-\fB-r\fR を指定すると、最新の入手可能バージョンに基づいてパッケージを照合し、イメージの構成済みパブリッシャーのリポジトリから、現在インストールされていないパッケージの情報を取得します (必要な場合)。このオプションを使用するときは、少なくとも 1 つのパッケージを指定する必要があります。\fB-r\fR を指定しない場合、デフォルトでインストール済みパッケージのみが表示されます。
-.sp
-\fB--license\fR を指定すると、パッケージのライセンステキストを表示します。このオプションは \fB-l\fR または \fB-r\fR と組み合わせることができます。
+最新の入手可能バージョンに基づいてパッケージを照合し、イメージの構成済み発行元のリポジトリから、現在インストールされていないパッケージの情報を取得します (必要な場合)。このオプションを使用するときは、少なくとも 1 つのパッケージを指定する必要があります。\fB-r\fR を指定しない場合、デフォルトでインストール済みパッケージのみが表示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--license\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージのライセンステキストを表示します。このオプションは \fB-l\fR または \fB-r\fR と組み合わせることができます。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg contents\fR [\fB-Hmr\fR] [\fB-a\fR \fIattribute\fR=\fIpattern\fR ...] [\fB-g\fR \fIpath_or_uri\fR ...] [\fB-o\fR \fI attribute\fR,...] [\fB-s\fR \fIsort_key\fR] [\fB-t\fR \fIaction_name\fR ...] [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+イメージ内のすべてのインストール済みパッケージの内容 (アクション属性) を表示します。オプションが指定されていない場合、現在のイメージにインストールされているアクションの \fBpath\fR 属性の値をアルファベット順で並べ替えて表示します。アクションとそれらの属性については、\fBpkg\fR(5) のマニュアルページのアクションに関する項目を参照してください。下の疑似属性名のリストも参照してください。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定したパッケージの内容のみを表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBcontents [\fB-Hmr\fR] [\fB-a\fR \fI attribute\fR=\fIpattern\fR ...] [\fB-g\fR \fI path_or_uri\fR ...] [\fB-o\fR \fIattribute\fR,...] [\fB-s\fR \fIsort_key\fR] [\fB-t\fR \fI action_type\fR ...] [\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+出力からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR \fIattribute\fR=\fI pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+名前がオプション引数で指定され、値がオプション引数 (属性名と等号に続く部分) の (glob) パターンに一致する属性を持つアクションに出力を限定します。複数の \fB-a\fR オプションを指定した場合、それらのいずれかに一致するアクションが表示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパッケージリポジトリまたはアーカイブからこのイメージにインストール可能なパッケージの情報を表示します。クライアント SSL 証明書が必要なリポジトリは、このオプションとともに使用できません。インストール可能なパッケージには、現在インストールされているパッケージと、バリアントやファセットの制限などのこのイメージへのインストールの条件を満たすその他のパッケージが含まれます。このオプションは複数回指定できます。\fB-g\fR を使用すると \fB-r\fR が暗黙的に指定されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内のパッケージの内容 (アクション属性) を表示します。デフォルトでは、\fBpath\fR 属性のみが表示されます。表示される属性は \fB-o\fR オプションで調べることができます。\fB-o\fR オプションは複数回指定できます。または、属性名をコンマで区切ることにより、1 つの \fB-o\fR オプションの引数として複数の属性を指定できます。要求された属性を持つアクションのみが表示されます。\fB-Ho action.raw\fR の短縮形として \fB-m\fR オプションも使用できます。
-.sp
-\fB-a\fR を指定すると、名前がオプション引数で指定され、値がオプション引数 (属性名と等号に続く部分) の (glob) パターンに一致する属性を持つアクションに出力を限定します。複数の \fB-a\fR オプションを指定した場合、それらのいずれかに一致するアクションが表示されます。
-.sp
-\fB-g\fR を指定すると、指定されたパッケージリポジトリまたはアーカイブを、操作のためのパッケージデータのソースとして使用します。このオプションは複数回指定できます。\fB-g\fR を使用すると \fB-r\fR が暗黙的に指定されます。
-.sp
-\fB-r\fR を指定すると、最新の入手可能バージョンに基づいてパッケージを照合し、イメージの構成済みパブリッシャーのリポジトリから、現在インストールされていないパッケージの情報を取得します (必要な場合)。このオプションを使用するときは、少なくとも 1 つのパッケージを指定する必要があります。\fB-r\fR を指定しない場合、デフォルトでインストール済みパッケージのみが表示されます。
-.sp
-\fB-s\fR を指定すると、指定されたアクション属性によってアクションをソートします。このオプションを指定しない場合、デフォルトではパスによって、または \fB-o\fR オプションで最初に指定された属性によってソートします。\fB-s\fR オプションは複数回指定できます。.
-.sp
-\fB-t\fR を指定すると、指定されたタイプのアクションのみを一覧表示します。複数のタイプをコンマ区切りリストで指定できます。このオプションは複数回指定できます。
-.sp
-\fB-H\fR を指定すると、一覧表示からヘッダーを省略します。
-.sp
-引数を指定しない場合、出力にはすべてのインストール済みパッケージが含まれます。別の方法として、複数の FMRI パターンを指定し、一致するパッケージの内容に表示を限定することができます。\fB-r\fR を使用するときは、1 つ以上の \fIpkg_fmri_pattern\fR を指定する必要があります。
-.sp
+このイメージにインストールできないアクションを含めて、指定されたパッケージのすべてのアクションのすべての属性を表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIattribute\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された属性を、リストの先頭属性の値に従って並べ替えて表示します。\fB-o\fR オプションは複数回指定できます。または、属性名をコンマで区切ることにより、1 つの \fB-o\fR オプションの引数として複数の属性を指定できます。要求された属性を持つアクションのみが表示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
+.ad
+.sp .6
+.RS 4n
+このイメージ内で構成された発行元のリポジトリからこのイメージにインストール可能なパッケージの最新バージョンの情報を表示します。インストール可能なパッケージには、現在インストールされているパッケージと、バリアントやファセットの制限などのこのイメージへのインストールの条件を満たすその他のパッケージが含まれます。このオプションを使用するときは、少なくとも 1 つのパッケージを指定する必要があります。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIsort_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたアクション属性で、アクションをソートします。このオプションを指定しない場合、デフォルトではパスによって、または \fB-o\fR オプションで最初に指定された属性によってソートします。\fB-s\fR オプションは複数回指定できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-t\fR \fIaction_name\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたアクションのみを一覧表示します。複数のアクションをコンマ区切りリストで指定できます。\fIaction_name\fR の値は、\fBpkg\fR(5) のマニュアルページの「アクション」内に一覧表示されているアクションのいずれかで、\fBfile\fR、\fBdirectory\fR、\fBdriver\fR、\fBdepend\fR、\fBset\fR などです。このオプションは複数回指定できます。
+.RE
+
 利便性のために、いくつかの特殊な疑似属性名を使用できます。
 .sp
 .ne 2
@@ -501,9 +976,9 @@
 .na
 \fB\fBaction.hash\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションがペイロードを伝送する場合、アクションのハッシュの値に対応します。
+.sp .6
+.RS 4n
+アクションがペイロードを伝送する場合、アクションのハッシュの値です。
 .RE
 
 .sp
@@ -512,9 +987,9 @@
 .na
 \fB\fBaction.key\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションのキー属性の値に対応します。たとえば、ファイルアクションの場合、これはファイルのパスです。
+.sp .6
+.RS 4n
+アクションのキー属性の値です。たとえば、\fBfile\fR アクションの場合、鍵属性はファイルのパスです。キー属性のないアクションもあります。
 .RE
 
 .sp
@@ -523,9 +998,9 @@
 .na
 \fB\fBaction.name\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションの名前に対応します。たとえば、ファイルアクションの場合、これは \fBfile\fR です。
+.sp .6
+.RS 4n
+アクションの名前です。たとえば、ファイルアクションの場合、これは \fBfile\fR です。
 .RE
 
 .sp
@@ -534,9 +1009,9 @@
 .na
 \fB\fBaction.raw\fR\fR
 .ad
-.RS 17n
-.rt  
-パッケージのマニフェストに登録されているアクションの完全な内容に対応します。これは \fBpkg contents -m\fR の出力の行に対応します。
+.sp .6
+.RS 4n
+一致するアクションのすべての属性。
 .RE
 
 .sp
@@ -545,9 +1020,9 @@
 .na
 \fB\fBpkg.fmri\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションを包含しているパッケージのフル形式 FMRI (たとえば、\fBpkg://solaris/web/[email protected],5.11-0.169:20110705T153434Z \fR) に対応します。
+.sp .6
+.RS 4n
+アクションを包含しているパッケージのフル形式 FMRI (たとえば、\fB pkg://solaris/group/feature/[email protected],5.11-0.175.0.0.0.2.1:20120705T153434Z\fR) です。
 .RE
 
 .sp
@@ -556,9 +1031,9 @@
 .na
 \fB\fBpkg.name\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションを包含しているパッケージの名前 (たとえば、\fBweb/amp\fR) に対応します。
+.sp .6
+.RS 4n
+アクションを包含しているパッケージの名前 (たとえば、\fBweb/amp\fR) です。
 .RE
 
 .sp
@@ -567,9 +1042,9 @@
 .na
 \fB\fBpkg.publisher\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションを包含しているパッケージのパブリッシャー (たとえば、\fBsolaris\fR) に対応します。
+.sp .6
+.RS 4n
+アクションを包含しているパッケージの発行元 (たとえば、\fBsolaris\fR) です。
 .RE
 
 .sp
@@ -578,12 +1053,12 @@
 .na
 \fB\fBpkg.shortfmri\fR\fR
 .ad
-.RS 17n
-.rt  
-アクションを包含しているパッケージの短縮形式 FMRI (たとえば、\fBpkg://solaris/web/[email protected],5.11-0.169\fR) に対応します。
+.sp .6
+.RS 4n
+アクションを包含しているパッケージのショート形式 FMRI (\fBpkg://solaris/group/feature/[email protected],5.11-0.175\fR など) です。
 .RE
 
-関連するサブコマンドは \fBcontents\fR および \fBsearch\fR で、これらはどちらも、パッケージの内容についてシステムを照会するために使用されます。\fBcontents\fR サブコマンドは、1 つ以上のパッケージ内のアクションを表示し、ユーザーが選択したオプションに基づいて出力をフィルタします。\fBsearch\fR サブコマンドは逆方向からクエリーを行い、ユーザーが指定したトークンを含むパッケージを探します。
+関連するサブコマンドは \fBcontents\fR および \fBsearch\fR であり、どちらもパッケージの内容についてシステムをクエリーします。\fBcontents\fR サブコマンドは、1 つまたは複数のインストールされているか、インストール可能なパッケージ内のアクションを、指定されたオプションに基づいて出力をフィルタ処理して表示します。\fBsearch\fR サブコマンドは逆方向からクエリーを行い、ユーザーが指定したトークンを含むすべてのパッケージの名前を表示します。
 .sp
 各サブコマンドで実行できるクエリーの一部は、他方でも実行できます。サブコマンドの選択は慎重に行ってください。クエリーによっては、もう一方のほうがより自然に実行できる場合があります。
 .RE
@@ -592,32 +1067,110 @@
 .ne 2
 .mk
 .na
-\fB\fBsearch [\fB-HIaflpr\fR] [\fB-o\fR \fI attribute\fR,...] [\fB-s\fR \fIrepo_uri\fR] \fI query\fR\fR\fR
+\fB\fBpkg search\fR [\fB-HIaflpr\fR] [\fB-o\fR \fIattribute\fR,...] [\fB-s\fR \fI repo_uri\fR] \fIquery\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fIquery\fR の一致を検索し、結果を表示します。次の \fIquery\fR の説明を参照してください。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+出力からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+大文字/小文字を区別する検索を使用します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+検索を実行して、一致するアクションに関する情報を表示します。これはデフォルトです。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-f\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fIquery\fR の一致を検索し、結果を表示します。どのトークンがインデックス化されるかはアクションに依存しますが、コンテンツハッシュとパス名を含めることができます。デフォルトでは、クエリーは完全一致する一連の条件として解釈されます。\fB?\fR および \fB*\fR 文字を \fBglob\fR(3C) 形式のワイルドカードとして使用することにより、より柔軟なクエリー一致が可能になります。
-.sp
-\fB-H\fR を指定するとヘッダーを省略します。.
-.sp
-\fB-I\fR を指定すると、大文字と小文字を区別する検索を使用します。
-.sp
-デフォルトでは、\fB-a\fR を一緒に指定すると、検索を実行し、一致したアクションについての情報を表示します。
-.sp
-\fBsearch\fR はデフォルトで、現在インストールされているバージョンよりも古いパッケージ、および現在の incorporation によって除外されているパッケージバージョンからの結果を取り除きます。パッケージバージョンに関係なくすべての結果を表示するには \fB-f\fR を使用します。
-.sp
-\fB-l\fR を指定すると、イメージのインストール済みパッケージを検索します。
-.sp
-\fB-o\fR を使用して結果の列を制御できます。\fB-o\fR オプションは複数回指定できます。または、属性名をコンマで区切ることにより、1 つの \fB-o\fR オプションの引数として複数の属性を指定できます。前述した疑似属性に加えて、検索結果用の次の属性が定義されています。
+パッケージのバージョンに関係なく、すべての結果を表示します。\fBsearch\fR はデフォルトで、現在インストールされているバージョンよりも古いパッケージ、および現在の incorporation によって除外されているパッケージバージョンからの結果を取り除きます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
+.ad
+.sp .6
+.RS 4n
+イメージのインストール済みパッケージを検索します。
+.sp
+\fB-l\fR と \fB-r\fR (または \fB-s\fR) の両方を同時に指定できます。この場合、ローカル検索とリモート検索の両方が実行されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR\fR
+.ad
+.sp .6
+.RS 4n
+一部のアクションが各クエリー条件に一致するパッケージを表示します。このオプションを使用することは、クエリーの各条件を山括弧 (\fB<>\fR) で囲むことと等価です。\fB<>\fR 演算子の詳細は、次の \fIquery\fR を参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
+.ad
+.sp .6
+.RS 4n
+イメージの発行元に対応するリポジトリを検索します。これはデフォルトです。
+.sp
+\fB-l\fR と \fB-r\fR (または \fB-s\fR) の両方を同時に指定できます。この場合、ローカル検索とリモート検索の両方が実行されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIattribute\fR\fR
+.ad
+.sp .6
+.RS 4n
+結果の列を制御します。\fB-o\fR オプションは複数回指定できます。または、属性名をコンマで区切ることにより、1 つの \fB-o\fR オプションの引数として複数の属性を指定できます。前述した疑似属性に加えて、検索結果用の次の属性が定義されています。
 .sp
 .ne 2
 .mk
 .na
 \fB\fBsearch.match\fR\fR
 .ad
-.RS 21n
-.rt  
-検索クエリーに一致した文字列に対応します。
+.sp .6
+.RS 4n
+検索クエリーに一致した文字列。
 .RE
 
 .sp
@@ -626,261 +1179,638 @@
 .na
 \fB\fBsearch.match_type\fR\fR
 .ad
-.RS 21n
-.rt  
-検索クエリーに一致した文字列を含んでいた属性に対応します。
+.sp .6
+.RS 4n
+検索クエリーに一致した文字列を含む属性。
+.RE
+
 .RE
 
-\fB-p\fR を指定すると、一部のアクションが各クエリー条件に一致するパッケージを表示します。このオプションを使用することは、クエリーの各条件を山括弧 (\fB<>\fR) で囲むことと等価です。\fB<>\fR 演算子についての説明は後述します。
-.sp
-デフォルトでは、\fB-r\fR を一緒に指定すると、イメージのパブリッシャーに対応するリポジトリを検索します。
-.sp
-\fB-s\fR を指定すると、指定された URI に位置する \fBpkg\fR(5) リポジトリを検索します。これは複数回指定できます。パッケージアーカイブはサポートされていません。
-.sp
-\fB-l\fR と \fB-r\fR (または \fB-s\fR) の両方を同時に指定できます。この場合、ローカル検索とリモート検索の両方が実行されます。
-.sp
-単純なトークン一致およびワイルドカード検索に加えて、より複雑なクエリー言語がサポートされています。単一引用符または二重引用符 (\fB\&'\fR または \fB"\fR) を使用することにより、語句を検索できます。\fBpkg\fR が実際に \fB\&'\fR または \fB"\fR を認識するように、必ずシェルを考慮に入れてください。
-.sp
-AND と OR を使用する論理検索がサポートされています。フィールド (構造化された) クエリーがサポートされています。これらのための構文は \fB\fIpkg_name\fR:\fI action_type\fR:\fIkey\fR:\fItoken\fR\fR です。欠けているフィールドは、暗黙的にワイルドカード化されます。\fB:basename:pkg\fR の検索は、\fBbasename\fR というキーを持ち、トークン \fBpkg\fR に一致するすべてのパッケージ内のすべてのアクションタイプに一致します。\fBpkg_name\fR および \fBtoken\fR フィールドでは明示的ワイルドカードがサポートされます。\fBaction_type\fR および \fBkey\fR は正確に一致する必要があります。
-.sp
-そのアクションを包含するパッケージにアクションを変換するには、\fB<>\fR を使用します。\fB-a\fR オプションを使用する場合、\fBtoken\fR を検索した結果は \fBtoken\fR に一致したアクションについての情報である一方で、\fB<token>\fR を検索した結果は、\fBtoken\fR に一致したアクションを包含しているパッケージの一覧です。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI に位置する \fBpkg\fR(5) リポジトリを検索します。これは複数回指定できます。パッケージアーカイブはサポートされていません。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBverify [\fB-Hqv\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fIquery\fR\fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内でパッケージのインストールを検証します。関連するパブリッシャーの現在の署名ポリシーが \fBignore\fR でない場合、各パッケージの署名がポリシーに基づいて検証されます。署名ポリシーが適用されるしくみについては、後述する「イメージプロパティー」の \fBsignature-policy\fR で説明します。
-.sp
-\fB-H\fR を指定すると、検証の出力からヘッダーを省略します。
-.sp
-\fB-q\fR を指定すると何も出力しませんが、致命的なエラーがある場合はエラーを返します。
-.sp
-\fB-v\fR を指定すると、パッケージに関する情報メッセージを含めます。
+デフォルトでは、\fIquery\fR は完全一致する一連の条件として解釈されます。\fB?\fR および \fB*\fR 文字を \fBglob\fR(3C) 形式のワイルドカードとして使用でき、より柔軟なクエリー一致が可能になります。
+.sp
+単純なトークン一致およびワイルドカード検索に加えて、より複雑なクエリー言語がサポートされています。単一引用符または二重引用符 (\fB\&'\fR または \fB"\fR) を使用することにより、語句を検索できます。\fBpkg\fR が実際に \fB\&'\fR または \fB"\fR を認識するように、必ずシェルを考慮に入れてください。
+.sp
+AND と OR を使用する論理検索がサポートされています。
+.sp
+どのトークンがインデックス化されるかはアクションに依存しますが、コンテンツハッシュとパス名を含めることができます。アクションとそれらの属性については、\fBpkg\fR(5) のマニュアルページのアクションに関する項目を参照してください。前述の \fBpkg contents\fR および \fB- o\fR 内の擬似属性名のリストも参照してください。
+.sp
+構造化されたクエリーは、次の構文でサポートされます:
+.sp
+.in +2
+.nf
+\fIpkg_name\fR:\fIaction_name\fR:\fIindex\fR:\fItoken\fR
+.fi
+.in -2
+
+\fIaction_name\fR の値は、\fBpkg\fR(5) マニュアルページの「アクション」に一覧表示されているアクションのいずれかです。\fIindex\fR は、アクションの属性です。\fIindex\fR の値は、\fItoken\fR と一致している必要があります。
+.sp
+すべてのアクション属性が検索可能なわけではありません。たとえば、\fBmode\fR は \fBfile\fR アクションの属性ですが、\fBmode\fR は \fIindex\fR の有効な値ではありません。
+.sp
+\fIindex\fR の一部の値は、アクション属性ではなく、ほかの属性から派生した値です。たとえば、パスの最後のコンポーネントを取ることにより、\fIindex\fR を、どのアクションの属性でもないが、\fBfile\fR または \fB dir\fR アクションの \fBpath\fR 属性から派生した \fBbasename\fR にできます。
+.sp
+アクションタイプが異なると、有効な \fIindex\fR 値も異なります。このドキュメントには、使用可能な値がすべて含まれているわけではありません。より有用な \fI index\fR 値には、ファイルシステムアクションの \fBbasename\fR および \fBpath\fR、\fBdepend\fR アクションの依存性タイプ (たとえば、\fBrequire\fR、\fB optional\fR、\fBgroup\fR)、および \fBdriver \fR アクションの \fBdriver_name\fR および \fBalias\fR などがあります。
+.sp
+特殊な \fIindex\fR 値の 1 つに、\fBset\fR アクションの \fBname\fR 属性の値があります。この場合、\fItoken\fR が、指定された \fB name\fR 属性に対応する \fBvalue\fR 属性の値と照合されます。たとえば、次の検索により、Development/Databases または System/Databases のいずれかに分類されるパッケージを検索します。「使用例」セクションで、SMF サービスを検索する例を参照してください。
+.sp
+.in +2
+.nf
+$ \fBpkg search info.classification:databases\fR
+.fi
+.in -2
+.sp
+
+構造化クエリー内の欠落したフィールドは、暗黙的にワイルドカード化されます。\fBbasename:pkg\fR の検索は、\fBbasename\fR の \fIindex\fR を持ち、次の部分出力に示すような \fItoken\fR \fBpkg\fR に一致するすべてのパッケージ内のすべてのアクションに一致します:
+.sp
+.in +2
+.nf
+$ \fBpkg search basename:pkg\fR
+INDEX    ACTION VALUE         PACKAGE
+basename dir    usr/share/pkg pkg:/package/[email protected]
+basename dir    var/sadm/pkg  pkg:/package/[email protected]
+basename dir    var/spool/pkg pkg:/package/[email protected]
+basename file   usr/bin/pkg   pkg:/package/[email protected]
+.fi
+.in -2
+.sp
+
+次の完全な出力に示すように、別のフィールドを追加すると検索が絞り込まれます:
+.sp
+.in +2
+.nf
+$ \fBpkg search file:basename:pkg\fR
+INDEX    ACTION VALUE       PACKAGE
+basename file   usr/bin/pkg pkg:/package/[email protected]
+.fi
+.in -2
+.sp
+
+\fIpkg_name\fR および \fItoken\fR フィールドでは明示的ワイルドカードがサポートされます。\fIaction_name\fR および \fI index\fR は、正確に一致する必要があります。
+.sp
+ファイルと依存関係の検索例については、「使用例」セクションを参照してください。
+.sp
+アクションをこれらのアクションを含むパッケージに変換するには、次の部分出力に示すように、\fB <>\fR を使用します:
+.sp
+.in +2
+.nf
+$ \fBpkg search \e<pkg\e>\fR
+PACKAGE                                  PUBLISHER
+pkg:/package/[email protected]  solaris
+pkg:/package/[email protected] solaris
+.fi
+.in -2
+.sp
+
+\fB-a\fR オプションを使用する場合 (デフォルト)、\fBtoken\fR を検索した結果は \fBtoken\fR に一致するアクションについての情報である一方で、\fB<token>\fR を検索した結果は、\fBtoken\fR に一致するアクションを包含しているパッケージの一覧です。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfix [\fB--accept\fR] [\fB--licenses\fR] [\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fBpkg verify\fR [\fB-Hqv\fR] [\fI pkg_fmri_pattern\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージ内で、インストールされているすべてのパッケージのインストールを検証します。関連する発行元の現在の署名ポリシーが \fBignore\fR でない場合、各パッケージの署名がポリシーに基づいて検証されます。署名ポリシーが適用されるしくみについては、後述する「イメージプロパティー」の \fBsignature-policy\fR で説明します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fBpkg verify\fR で報告されたエラーをすべて修正します。インストール済みパッケージの内容は、独自の内容解析に基づいて検証されるため、ほかのプログラムの場合とは異なる結果が返されることがあります。
-.sp
-\fB--accept\fR は、更新またはインストールされるパッケージのライセンス条項に同意することを示します。このオプションを指定しないと、パッケージのライセンスに同意が必要になった場合、操作は失敗します。
-.sp
-\fB--licenses\fR を指定すると、この操作の一環としてインストールまたは更新されるパッケージのすべてのライセンスを表示します。
+現在のイメージ内で、指定されたインストール済みパッケージのインストールのみを検証します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+検証の出力からヘッダーを省略します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrevert [\fB-nv\fR] [\fB--no-be-activate \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] (\fB--tagged\fR \fItag-name\fR ... | \fIpath-to-file\fR ...)\fR\fR
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+何も出力しませんが、致命的なエラーがある場合はエラーを返します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージに関する情報メッセージを含めます。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg fix\fR [\fB--accept\fR] [\fB--licenses\fR] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-ファイルを配布時の状態に戻します。特定の値でタグ付けされたすべてのファイル、または個別ファイルを元に戻すことができます。ファイルの所有権および保護も復元されます。
-.LP
-注意 - 
-.sp
-.RS 2
-一部の編集可能ファイルをデフォルト値に戻すと、システムがブート不可になったり、その他の異常動作の原因になったりする可能性があります。
+\fBpkg verify\fR で報告されたエラーをすべて修正します。インストール済みパッケージの内容は、独自の内容解析に基づいて検証されるため、ほかのプログラムの場合とは異なる結果が返されることがあります。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージ内で、指定されたインストール済みパッケージに対する \fBpkg verify\fR により報告されたエラーを修正します。
 .RE
-その他すべてのオプションの使用法および効果については、前述した \fBinstall\fR コマンドを参照してください。
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--accept\fR\fR
+.ad
+.sp .6
+.RS 4n
+更新またはインストールされるパッケージのライセンス条項に同意することを示します。このオプションを指定しないと、パッケージのライセンスに同意が必要になった場合、操作は失敗します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--licenses\fR\fR
+.ad
+.sp .6
+.RS 4n
+この操作の一環としてインストールまたは更新されるパッケージのすべてのライセンスを表示します。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBmediator [\fB-aH\fR] [\fB-F\fR \fI format\fR] [\fImediator\fR ...]\fR\fR
+\fB\fBpkg revert\fR [\fB-nv\fR] [\fB- -no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] (\fB--tagged\fR \fI tag-name\fR ... | \fIpath-to-file\fR ...)\fR
 .ad
 .sp .6
 .RS 4n
-すべてのメディエータの、または引数が使用されている場合は指定されたメディエータのみの、現在選択されているバージョンと実装を表示します。
-.sp
-\fB-a\fR を指定すると、現在インストールされているパッケージに設定可能なメディエーションを一覧表示します。
-.sp
-\fB-F\fR は代替の出力形式を指定します。現時点では \fBtsv\fR (タブ区切り値) のみが有効です。
-.sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+\fBpkg\fR(5) パッケージにより配布されたパッケージを、配布時の状態に戻します。ファイルの所有権および保護も復元されます。
+.LP
+注意 - 
+.sp
+.RS 2
+一部の編集可能ファイルをデフォルト値に戻すと、システムがブート不可になったり、その他の異常動作の原因になったりする可能性があります。
+.RE
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--tagged\fR \fItag-name\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fItag-name\fR でタグ付けされたすべてのファイルを元に戻します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpath-to-file\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたファイルを元に戻します。
+.RE
+
+その他のすべてのオプションについては、前述の \fBinstall\fR コマンドを参照してください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-mediator [\fB-nv\fR] [\fB-I\fR \fI implementation\fR] [\fB-V\fR \fIversion\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI mediator\fR ...\fR\fR
+\fB\fBpkg mediator\fR [\fB-aH\fR] [\fB-F\fR \fIformat\fR] [\fImediator\fR ...] \fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内の指定されたメディエータのバージョンと実装を設定します。
-.sp
-\fB-I\fR は、使用するメディエート対象インタフェースの実装を設定します。デフォルトでは、バージョンが指定されない場合、すべての実装バージョンが許可されます。バージョンなしで実装を指定するには、アット記号 (@) を付加します。
-.sp
-\fB-V\fR は、使用するメディエート対象インタフェースのバージョンを設定します。
-.sp
-指定されたメディエータのバージョンと実装のどちらかまたは両方が現在入手できない場合、指定されたメディエータを使用するリンクはすべて削除されます。
-.sp
-その他すべてのオプションの使用方法および効果については、前述の \fBinstall\fR コマンドを参照してください。
+現在選択されているバージョンやすべてのメディエータの実装を表示します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fImediator\fR\fR
+.ad
+.sp .6
+.RS 4n
+現在選択されているバージョンや指定されたメディエータの実装のみを表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunset-mediator [\fB-nvIV\fR] [\fB--no-be-activate \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] \fImediator \fR ...\fR\fR
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+現在インストールされているパッケージに設定可能なメディエーションを一覧表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR\fR
 .ad
 .sp .6
 .RS 4n
-指定されたメディエータのバージョンと実装をシステムデフォルトに戻します。
-.sp
-\fB-I\fR は、メディエート対象インタフェースの実装のみを元に戻します。
-.sp
-\fB-V\fR は、メディエート対象インタフェースのバージョンのみを元に戻します。.
-.sp
-その他すべてのオプションの使用方法および効果については、前述の \fBinstall\fR コマンドを参照してください。
+代替出力形式を指定します。現時点では \fBtsv\fR (タブ区切り値) のみが有効です。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBvariant [\fB-H\fR] [\fIvariant_spec \fR]\fR\fR
+\fB\fBpkg set-mediator\fR [\fB-nv\fR] [\fB-I\fR \fIimplementation\fR] [\fB-V\fR \fI version\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB- -require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fImediator\fR ... \fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージ内の指定されたメディエータのバージョンと実装を設定します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR \fIimplementation\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用するメディエート対象インタフェースの実装を設定します。デフォルトでは、バージョンが指定されない場合、すべての実装バージョンが許可されます。バージョンなしで実装を指定するには、アット記号 (@) を付加します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-V\fR \fIversion\fR\fR
 .ad
 .sp .6
 .RS 4n
-すべてのバリアントの、または引数が使用されている場合は指定されたバリアントのみの、現在値を表示します。
-.sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+使用するメディエート対象インタフェースのバージョンを設定します。
+.RE
+
+指定されたメディエータのバージョンと実装のどちらかまたは両方が現在入手できない場合、指定されたメディエータを使用するリンクはすべて削除されます。
+.sp
+その他のすべてのオプションについては、前述の \fBinstall\fR コマンドを参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unset-mediator\fR [\fB-nvIV\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fImediator\fR ... \fR
+.ad
+.sp .6
+.RS 4n
+指定されたメディエータのバージョンと実装をシステムデフォルトに戻します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+メディエート対象インタフェースの実装のみを元に戻します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-V\fR \fR
+.ad
+.sp .6
+.RS 4n
+メディエート対象インタフェースのバージョンのみを元に戻します。
+.RE
+
+その他のすべてのオプションについては、前述の \fBinstall\fR コマンドを参照してください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBchange-variant [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI variant_spec\fR=\fIinstance\fR ...\fR\fR
+\fB\fBpkg variant\fR [\fB-H\fR] [\fB variant.\fR\fIvariant_name\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+このイメージに設定されているすべてのバリアントの現在値を表示します。バリアントの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.sp
+.ne 2
+.mk
+.na
+\fB\fBvariant.\fR\fIvariant_name\fR\fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内の指定されたバリアントを変更します。
-.sp
-オプションの使用法および効果については、前述の \fBinstall\fR コマンドを参照してください。
+このイメージで設定されている、指定されたバリアントのみの現在値を表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfacet [\fB-H\fR] [\fIfacet_spec\fR] \fR\fR
+\fB\fBpkg change-variant\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR |\fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIvariant_name\fR=\fI value\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-引数を指定しない場合、すべてのファセットの現在値を表示します。引数を指定した場合、各ファセットの真偽を評価して結果を出力します。
-.sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+現在のイメージに設定され、指定されているバリアントの値を変更します。
+.sp
+バリアントの値を変更すると、パッケージの内容が削除、更新、またはインストールされることがあります。バリアントの値を変更すると、新しいイメージ構成を満たすために、パッケージ全体がインストール、更新、または削除されることもあります。バリアントの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.sp
+オプションの説明については、前述の \fBinstall\fR コマンドを参照してください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBchange-facet [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI facet_spec\fR=[True|False|None] ...\fR\fR
+\fB\fBpkg facet\fR [\fB-H\fR] [\fI facet_name\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+\fBpkg change-facet\fR コマンドを使用してこのイメージに明示的に設定されているすべてのファセットの現在の値を表示します。ファセットの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIfacet_name\fR\fR
 .ad
 .sp .6
 .RS 4n
-現在のイメージ内の指定されたファセットを変更します。
-.sp
-ファセットは \fBTrue\fR または \fBFalse\fR に設定できます。ファセットを \fBNone\fR に設定すると、そのファセットの仕様が現在のイメージから削除されます。
-.sp
-オプションの使用法および効果については、前述の \fBinstall\fR コマンドを参照してください。
+このイメージに設定されている、指定されたファセットのみの現在値を表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBavoid [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg change-facet\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIfacet_name\fR=[\fB True\fR|\fBFalse\fR|\fBNone\fR] ...\fR
+.ad
+.sp .6
+.RS 4n
+現在のイメージに設定され、指定されたファセットの値を変更します。
+.sp
+ファセットは \fBTrue\fR または \fBFalse\fR に設定できます。ファセットを \fBNone\fR に設定すると、\fBTrue\fR のデフォルト値がそのファセットに適用されるため、ファセットに依存するすべてのアクションがインストールされます。アクションについては、\fBpkg\fR(5) のマニュアルページのアクションに関する項目を参照してください。
+.sp
+ファセットの値を変更すると、パッケージの内容が削除、更新、またはインストールされることがあります。ファセットの値を変更すると、新しいイメージ構成を満たすために、パッケージ全体がインストール、更新、または削除されることもあります。ファセットの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.sp
+オプションの説明については、前述の \fBinstall\fR コマンドを参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg avoid\fR [\fIpkg_fmri_pattern\fR ...] \fR
+.ad
+.sp .6
+.RS 4n
+回避対象の各パッケージを、そのパッケージにグループ依存関係を持つパッケージとともに表示します。
+.sp
+回避リストに登録されているパッケージは、要求された依存関係を満たすために必要であればインストールされます。その依存関係が削除された場合、パッケージはアンインストールされます。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
 .ad
 .sp .6
 .RS 4n
 指定されたパターンに現在一致するパッケージ名を回避リストに登録することにより、それらがグループ依存関係のターゲットである場合にそれらを回避します。現在インストールされていないパッケージのみを回避できます。パッケージが現在グループ依存関係のターゲットである場合、パッケージをアンインストールするとそのパッケージは回避リストに登録されます。
-.sp
-引数を指定しない場合、回避対象の各パッケージを、そのパッケージにグループ依存関係を持つパッケージとともに表示します。
-.sp
-回避リストに登録されているパッケージは、要求された依存関係を満たすために必要であればインストールされます。その依存関係が削除された場合、パッケージはアンインストールされます。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunavoid [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg unavoid\fR [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+回避対象のパッケージのリストを表示します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
 .ad
 .sp .6
 .RS 4n
 指定されたパッケージを回避リストから削除します。回避リストに登録されており、インストール済みパッケージのグループ依存関係に一致するパッケージは、このサブコマンドを使用して削除できません。グループ依存性に一致するパッケージを回避リストから削除するには、パッケージをインストールします。
-.sp
-引数を指定しない場合、回避対象パッケージの一覧を表示します。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg freeze\fR [\fB-n\fR] [\fB-c \fR \fIreason\fR] [\fIpkg_fmri_pattern\fR] ...\fR
+.ad
+.sp .6
+.RS 4n
+現在凍結されているパッケージについての情報 (パッケージ名、バージョン、パッケージがいつ凍結されたか、パッケージの凍結に関連付けられた理由があればその理由) が表示されます。
+.sp
+パッケージを凍結しても、そのパッケージを削除できなくなるわけではありません。パッケージが削除される場合に警告は表示されません。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたパッケージを指定されたバージョンに凍結します。バージョンを指定しない場合、パッケージがインストールされている必要があり、そのインストール済みバージョンで凍結されます。すでに凍結されているパッケージを凍結すると、新しく指定されたバージョンによって凍結バージョンが置き換えられます。
+.sp
+凍結されているパッケージをインストールまたは更新するときは、凍結された時点のバージョンと一致するバージョンである必要があります。たとえば、パッケージが 1.2 で凍結された場合、1.2.1、1.2.9、1.2.0.0.1 などのバージョンに更新することはできます。そのパッケージは 1.3 または 1.1 で終了することはできません。\fIpkg_fmri_pattern\fR で提供されるパブリッシャーは、一致するパッケージを検索するために使用されます。ただし、パブリッシャー情報は凍結の一環として記録されません。パッケージは発行元ではなくバージョンのみに関して凍結されます。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfreeze [\fB-n\fR] [\fB-c\fR \fI reason\fR] [\fIpkg_fmri_pattern\fR] ...\fR\fR
+\fB\fB-c\fR \fIreason\fR\fR
+.ad
+.sp .6
+.RS 4n
+凍結されるパッケージとともに理由を記録します。\fI\fR凍結が原因でインストールまたは更新に失敗する場合、その理由が示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
 .ad
 .sp .6
 .RS 4n
-指定されたパッケージを指定されたバージョンに凍結します。バージョンを指定しない場合、パッケージがインストールされている必要があり、そのインストール済みバージョンで凍結されます。凍結されているパッケージをインストールまたは更新するときは、凍結された時点のバージョンと一致するバージョンである必要があります。たとえば、パッケージが 1.2 で凍結された場合、1.2.1、1.2.9、1.2.0.0.1 などのバージョンに更新することはできます。そのパッケージを 1.3 や 1.1 などにすることはできません。一致するパッケージの検索には、\fIpkg_fmri_pattern\fR で提示されたパブリッシャーが使用されます。ただし、パブリッシャー情報は凍結の一環として記録されません。パッケージはパブリッシャーではなくバージョンのみに関して凍結されます。すでに凍結されているパッケージを凍結すると、新しく指定されたバージョンによって凍結バージョンが置き換えられます。
-.sp
-パッケージを提供しない場合、現在凍結されているパッケージについての情報 (パッケージ名、バージョン、パッケージがいつ凍結されたか、関連付けられた理由があればその理由) が表示されます。
-.sp
-パッケージを凍結しても、そのパッケージを削除できなくなるわけではありません。パッケージが削除される場合に警告は表示されません。
-.sp
-\fB-c\fR を指定すると、凍結されるパッケージとともに理由を記録します。\fI\fR凍結が原因でインストールまたは更新に失敗する場合、その理由が示されます。
-.sp
-\fB-n\fR を指定すると、操作を試しに実行し、凍結されるパッケージの一覧を表示しますが、実際にはどのパッケージも凍結しません。
+凍結操作を試しに実行し、凍結されるパッケージの一覧を表示しますが、実際にはどのパッケージも凍結しません。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unfreeze\fR [\fB-n\fR] [\fI pkg_name_pattern\fR] ...\fR
+.ad
+.sp .6
+.RS 4n
+現在凍結されているパッケージについての情報 (パッケージ名、バージョン、パッケージがいつ凍結されたか、パッケージの凍結に関連付けられた理由があればその理由) が表示されます。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+凍結によって適用される制約を、指定されたパッケージから削除します。バージョンを提供しても無視されます。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunfreeze [\fB-n\fR] [\fIpkg_name_pattern \fR] ...\fR\fR
+\fB\fB-n\fR\fR
 .ad
 .sp .6
 .RS 4n
-凍結によって適用される制約を、指定されたパッケージから削除します。バージョンを提供しても無視されます。
-.sp
-\fB-n\fR を指定すると、凍結解除を試しに実行し、凍結解除されるパッケージの一覧を表示しますが、実際にはどのパッケージも凍結解除しません。
+凍結解除操作を試しに実行し、凍結解除されるパッケージの一覧を表示しますが、実際にはどのパッケージも凍結解除しません。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBproperty [\fB-H\fR] [\fIpropname \fR ...]\fR\fR
+\fB\fBpkg property\fR [\fB-H\fR] [\fI propname\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-イメージプロパティー情報を表示します。引数を指定しない場合、すべてのイメージプロパティーの名前および値を表示します。プロパティー名の特定のリストが要求された場合、それらのプロパティーの名前および値を表示します。
-.sp
-\fB-H\fR を指定すると、一覧表示からヘッダーを省略します。
+すべてのイメージプロパティーの名前と値を表示します。イメージプロパティーの説明については、下の「イメージプロパティー」を参照してください。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpropname\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたプロパティーのみの名前と値を表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-property \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-property\fR \fIpropname\fR \fI propvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -891,7 +1821,7 @@
 .ne 2
 .mk
 .na
-\fB\fBadd-property-value \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fBpkg add-property-value\fR \fIpropname \fR \fIpropvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -902,7 +1832,7 @@
 .ne 2
 .mk
 .na
-\fB\fBremove-property-value \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fBpkg remove-property-value\fR \fIpropname \fR \fIpropvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -913,7 +1843,7 @@
 .ne 2
 .mk
 .na
-\fB\fBunset-property \fIpropname\fR ... \fR\fR
+\fB\fBpkg unset-property\fR \fIpropname\fR ... \fR
 .ad
 .sp .6
 .RS 4n
@@ -924,110 +1854,473 @@
 .ne 2
 .mk
 .na
-\fB\fBpublisher [\fB-HPn\fR] [\fIpublisher \fR ...]\fR\fR
+\fB\fBpkg publisher\fR [\fB-HPn\fR] [\fB-F\fR \fIformat\fR] [\fIpublisher\fR ...] \fR
+.ad
+.sp .6
+.RS 4n
+すべての発行元、それらの起点 URI、およびミラーの一覧を、検索の優先順に従って表示します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のみの詳細な構成を表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.sp .6
+.RS 4n
+発行元検索順の先頭の発行元のみを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+有効な発行元のみを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR\fR
+.ad
+.sp .6
+.RS 4n
+代替出力形式を指定します。現時点では \fBtsv\fR (タブ区切り値) のみが有効です。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-publisher\fR [\fB-Ped\fR] [\fB-k\fR \fIssl_key\fR] [\fB-c\fR \fI ssl_cert\fR] [\fB-g\fR \fIorigin_to_add\fR | \fB- -add-origin\fR \fIorigin_to_add\fR ...] [\fB-G\fR \fI origin_to_remove\fR | \fB--remove-origin\fR \fIorigin_to_remove \fR ...] [\fB-m\fR \fImirror_to_add\fR | \fB- -add-mirror\fR \fImirror_to_add\fR ...] [\fB-M\fR \fI mirror_to_remove\fR | \fB--remove-mirror\fR \fImirror_to_remove \fR ...] [\fB--enable\fR] [\fB--disable\fR] [\fB--no-refresh\fR] [\fB--reset-uuid\fR] [\fB--non-sticky \fR] [\fB--sticky\fR] [\fB--search-after\fR \fI publisher\fR] [\fB--search-before\fR \fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR \fI path_to_CA\fR] [\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--set-property\fR \fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR \fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR \fIname_of_property_to_delete \fR] [\fB--proxy\fR \fIproxy_to_use\fR] \fI publisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+既存の発行元を更新するか、発行元を追加します。検索順に影響するオプションを指定しない場合、新しいパブリッシャーは検索順の末尾に付加され、最後に検索されます。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.br
+.na
+\fB\fB--search-first\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元を、検索順の先頭に設定します。新しいパッケージをインストールするとき、このパブリッシャーが最初に検索されます。インストール済みパッケージの更新は、そのパブリッシャーが sticky であるかぎり、そのパッケージを最初に提供した同じパブリッシャーから取得されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--non-sticky\fR\fR
+.ad
+.sp .6
+.RS 4n
+この発行元よりも上位にランクされる発行元が、この発行元から最初にインストールされたパッケージに更新を提供できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--sticky\fR\fR
 .ad
 .sp .6
 .RS 4n
-パブリッシャー情報を表示します。引数を指定しない場合、すべてのパブリッシャー、それらの起点 URI、およびミラーの一覧を、検索の優先順に従って表示します。特定のパブリッシャーが要求された場合、それらのパブリッシャーの詳細な構成を表示します。
-.sp
-\fB-H\fR を指定すると、一覧表示からヘッダーを省略します。
-.sp
-\fB-P\fR を指定すると、パブリッシャー検索順の先頭のパブリッシャーのみを表示します。
-.sp
-\fB-n\fR を指定すると、有効になっているパブリッシャーのみを表示します。.
+この発行元からインストールされたパッケージへの更新も、この発行元から取得する必要があります。これはデフォルトの動作です。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--search-before\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+追加または変更される発行元が、このオプションで指定された発行元の前に検索されるように、発行元検索順序を変えます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--search-after\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+追加または変更される発行元が、このオプションで指定された発行元のあとに検索されるように、発行元検索順序を変えます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--approve-ca-cert\fR \fIpath_to_CA\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された証明書を信頼できる CA 証明書として追加します。ユーザーが承認した CA 証明書の PEM 表現のハッシュは、\fBpkg publisher\fR コマンドの詳細出力に一覧表示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された PEM 表現のハッシュを持つ証明書を失効済みとして扱います。ユーザーが失効させた CA 証明書のハッシュは、\fBpkg publisher\fR コマンドの詳細出力に一覧表示されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたハッシュを持つ証明書を、承認済み証明書のリストおよび失効済み証明書のリストから削除します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--set-property\fR \fIname_of_property\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+既存の発行元プロパティーを更新するか、または新しい発行元プロパティーを追加します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+既存の発行元プロパティーに値を追加するか、または新しい発行元プロパティーを追加します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--remove-property-value\fR \fIname_of_property \fR=\fIvalue_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+既存の発行元プロパティーから値を削除します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--unset-property\fR \fIname_of_property_to_delete \fR\fR
+.ad
+.sp .6
+.RS 4n
+既存の発行元プロパティーを削除します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+クライアント SSL 鍵を指定します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+クライアント SSL 証明書を指定します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-publisher [\fB-Ped\fR] [\fB-k\fR \fI ssl_key\fR] [\fB-c\fR \fIssl_cert\fR] [\fB-g\fR \fIorigin_to_add\fR | \fB--add-origin \fR \fIorigin_to_add\fR ...] [\fB-G\fR \fI origin_to_remove\fR | \fB--remove-origin\fR \fIorigin_to_remove \fR ...] [\fB-m\fR \fImirror_to_add\fR | \fB- -add-mirror\fR \fImirror_to_add\fR ...] [\fB-M\fR \fI mirror_to_remove\fR | \fB--remove-mirror\fR \fImirror_to_remove \fR ...] [\fB-p\fR \fIrepo_uri\fR] [\fB--enable\fR] [\fB--disable\fR] [\fB--no-refresh\fR] [\fB--reset-uuid\fR] [\fB--non-sticky\fR] [\fB--sticky\fR] [\fB--search-after\fR \fIpublisher\fR] [\fB--search-before \fR \fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR \fIpath_to_CA\fR] [\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove\fR] [\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove\fR] [\fB--set-property\fR \fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR \fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR \fIname_of_property_to_delete \fR] [\fIpublisher\fR]\fR\fR
+\fB\fB-g\fR \fIorigin_to_add\fR\fR
+.ad
+.br
+.na
+\fB\fB--add-origin\fR \fIorigin_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはパスを、特定の発行元の起点として追加します。これはパッケージのリポジトリまたはアーカイブの場所にしてください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-G\fR \fIorigin_to_remove\fR\fR
+.ad
+.br
+.na
+\fB\fB--remove-origin\fR \fIorigin_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元の起点のリストから URI またはパスを削除します。特殊値 \fB*\fR を使用して、すべての起点を削除することができます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージの発行元用のリポジトリへのアクセスを試みません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--reset-uuid\fR\fR
 .ad
 .sp .6
 .RS 4n
-既存のパブリッシャーを更新するか、パッケージパブリッシャーを追加します。検索順に影響するオプションを指定しない場合、新しいパブリッシャーは検索順の末尾に付加され、最後に検索されます。
-.sp
-\fB-P\fR または \fB--search-first\fR を指定すると、指定されたパブリッシャーを検索順の先頭に設定します。新しいパッケージをインストールするとき、このパブリッシャーが最初に検索されます。インストール済みパッケージの更新は、そのパブリッシャーが sticky であるかぎり、そのパッケージを最初に提供した同じパブリッシャーから取得されます。\fB-P\fR または \fB--search-first\fR を \fB-p\fR とともに使用すると、追加されたパブリッシャーのみが検索順序の先頭に配置されます。
-.sp
-\fB--non-sticky\fR は、このパブリッシャーよりも上位にランクされるパブリッシャーが、このパブリッシャーから最初にインストールされたパッケージに更新を提供できることを指定します。
-.sp
-\fB--sticky\fR は、このパブリッシャーからインストールされたパッケージへの更新を引き続きこのパブリッシャーから取得する必要があることを指定します。これはデフォルトの動作です。
-.sp
-\fB--search-before\fR は、変更されるパブリッシャーが指定されたパブリッシャーの前に検索されるように、パブリッシャー検索順序を変えます。\fB-p\fR とともに使用すると、\fB--search-before\fR は追加されるパブリッシャーのみに適用されます。
-.sp
-\fB--search-after\fR は、変更されるパブリッシャーが指定されたパブリッシャーのあとに検索されるように、パブリッシャー検索順序を変えます。\fB-p\fR とともに使用すると、\fB--search-after\fR は追加されるパブリッシャーのみに適用されます。
-.sp
-\fB--approve-ca-cert\fR を指定すると、指定された証明書を、信頼できる CA 証明書として追加します。ユーザーが承認した CA 証明書の PEM 表現のハッシュは、\fBpkg publisher\fR コマンドの詳細出力に一覧表示されます。
-.sp
-\fB--revoke-ca-cert\fR を指定すると、指定された PEM 表現のハッシュを持つ証明書を失効済みとして扱います。ユーザーが失効させた CA 証明書のハッシュは、\fBpkg publisher\fR コマンドの詳細出力に一覧表示されます。
-.sp
-\fB--unset-ca-cert\fR を指定すると、指定されたハッシュを持つ証明書を、承認済み証明書のリストおよび失効済み証明書のリストから削除します。
-.sp
-\fB--set-property\fR は、既存のパブリッシャープロパティーを更新するか、新しいパブリッシャープロパティーを追加します。
-.sp
-\fB--add-property-value\fR は、既存のパブリッシャープロパティーに値を追加するか、新しいパブリッシャープロパティーを追加します。
-.sp
-\fB--remove-property-value\fR は、既存のパブリッシャープロパティーから値を削除します。
-.sp
-\fB--unset-property\fR は、既存のパブリッシャープロパティーを削除します。
-.sp
-\fB-c\fR はクライアント SSL 証明書を、\fB-k\fR は SSL 鍵をそれぞれ指定します。
-.sp
-\fB-g\fR (\fB--add-origin\fR) は、指定された URI またはパスを、指定されたパブリッシャーの起点として追加します。これはパッケージのリポジトリまたはアーカイブの場所にしてください。
-.sp
-\fB-G\fR (\fB--remove-origin\fR) は、指定されたパブリッシャーの起点のリストから URI またはパスを削除します。特殊値 \fB*\fR を使用して、すべての起点を削除することができます。
-.sp
-\fB--no-refresh\fR を指定すると、入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージのパブリッシャー用のリポジトリへのアクセスを試みません。
-.sp
-\fB--reset-uuid\fR は、このイメージをそのパブリッシャーに対して識別する新しい一意識別子を選択します。
-.sp
-\fB-m\fR (\fB--add-mirror\fR) は、指定されたパブリッシャーのミラーとして URI を追加します。
-.sp
-\fB-M\fR (\fB--remove-mirror\fR) は、指定されたパブリッシャーのミラーのリストから URI を削除します。特殊値 \fB*\fR を使用して、すべてのミラーを削除することができます。
-.sp
-\fB-p\fR は、指定されたリポジトリ URI からパブリッシャー構成情報を取得します。パブリッシャーを指定した場合、一致するパブリッシャーのみが追加または更新されます。パブリッシャーを指定しない場合、すべてのパブリッシャーが必要に応じて追加または更新されます。このオプションは \fB-g\fR、\fB--add-origin\fR、\fB--G\fR、\fB--remove-origin\fR、\fB-m\fR、\fB--add-mirror\fR、\fB-M\fR、\fB--remove-mirror\fR、\fB--disable\fR、\fB--enable\fR、\fB--no-refresh\fR、または \fB--reset-uuid\fR の各オプションとは組み合わせることができません。
-.sp
-\fB-e\fR (\fB--enable\fR) はパブリッシャーを有効にします。\fB-d\fR (\fB--disable\fR) はパブリッシャーを無効にします。無効にされたパブリッシャーは、パッケージリストの生成時に、または特定のパッケージ操作 (インストール、アンインストール、および更新) で使用されません。ただし、無効なパブリッシャーのプロパティーを設定または表示することはできます。パブリッシャーが 1 つだけの場合は、無効にすることはできません。
+このイメージをその発行元に対して識別する新しい一意識別子を選択します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR \fImirror_to_add\fR\fR
+.ad
+.br
+.na
+\fB\fB--add-mirror\fR \fImirror_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+URI を指定された発行元のミラーとして追加します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-M\fR \fImirror_to_remove\fR\fR
+.ad
+.br
+.na
+\fB\fB--remove-mirror\fR \fImirror_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のミラーのリストから URI を削除します。特殊値 \fB*\fR を使用して、すべてのミラーを削除することができます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-e\fR\fR
+.ad
+.br
+.na
+\fB\fB--enable\fR\fR
+.ad
+.sp .6
+.RS 4n
+発行元を有効にします。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-d\fR\fR
+.ad
+.br
+.na
+\fB\fB--disable\fR\fR
+.ad
+.sp .6
+.RS 4n
+発行元を無効にします。無効にされたパブリッシャーは、パッケージリストの生成時に、または特定のパッケージ操作 (インストール、アンインストール、および更新) で使用されません。ただし、無効なパブリッシャーのプロパティーを設定または表示することはできます。発行元が 1 つだけの場合は、無効にすることはできません。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunset-publisher \fIpublisher\fR ... \fR\fR
+\fB\fB--proxy\fR \fIproxy_to_use\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定した Web プロキシ URI を使用して、指定した起点 (\fB-g\fR) またはミラー(\fB-m\fR) のコンテンツを取得します。プロキシ値は、発行元の構成の一部として格納されます。実行時に、\fB$http_proxy\fR または関連する環境変数は、このプロキシ設定をオーバーライドします。受け入れられる環境変数名のリストについては、\fBcurl\fR(1) のマニュアルページを参照してください。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-publisher\fR \fB-p\fR \fI repo_uri\fR [\fB-Ped\fR] [\fB-k\fR \fIssl_key \fR] [\fB-c\fR \fIssl_cert\fR] [\fB- -non-sticky\fR] [\fB--sticky\fR] [\fB--search-after\fR \fI publisher\fR] [\fB--search-before\fR \fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR \fI path_to_CA\fR] [\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--set-property\fR \fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR \fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR \fIname_of_property_to_delete \fR] [\fB--proxy\fR \fIproxy_to_use\fR] [\fIpublisher\fR]\fR
 .ad
 .sp .6
 .RS 4n
-指定されたパブリッシャーに関連付けられた構成を削除します。
+\fIrepo_uri\fR リポジトリ URI から発行元構成情報を取得します。
+.sp
+発行元オペランドがこの \fBset-publisher\fR サブコマンドに指定されている場合、その発行元のみが追加または更新されます。発行元を指定しない場合、\fIrepo_uri\fR 内のすべての発行元が必要に応じて追加または更新されます。
+.sp
+オプションの説明については、前述の \fBset-publisher\fR コマンドを参照してください。\fB-p\fR と同時に使用する場合、\fB-P\fR、\fB--search-first \fR、\fB--search-before\fR、および \fB--search-after\fR オプションは追加された発行元のみに適用され、更新された発行元には適用されません。
+.sp
+\fB-p\fR オプションは、\fB-g\fR、\fB--add-origin\fR、\fB-G\fR、\fB--remove-origin\fR、\fB-m\fR、\fB--add-mirror\fR、\fB-M\fR、\fB--remove-mirror\fR、\fB--disable\fR、\fB--enable\fR、\fB--no-refresh\fR、または \fB--reset-uuid\fR オプションと組み合わせることはできません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unset-publisher\fR \fIpublisher \fR ...\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元に関連付けられた構成を削除します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg history\fR [\fB-HNl\fR] [\fB-t\fR [\fItime\fR | \fItime\fR-\fI time\fR],...] [\fB-o\fR \fIcolumn\fR,...] [\fB-n\fR \fInumber\fR]\fR
+.ad
+.sp .6
+.RS 4n
+該当するイメージのコマンド履歴を表示します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBhistory [\fB-Hl\fR] [\fB-t\fR [\fI time\fR | \fItime\fR-\fItime\fR],...] [\fB-o\fR \fIcolumn\fR,...] [\fB-n\fR \fI number\fR]\fR\fR
+\fB\fB-t\fR \fItime\fR\fR
+.ad
+.br
+.na
+\fB\fB-t\fR \fItime\fR-\fItime\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fB%Y-%m-%dT%H:%M:%S\fR 形式のタイムスタンプのコンマ区切りリストでログレコードを表示します (\fB strftime\fR(3C) を参照)。日時の範囲を指定するには、開始と終了のタイムスタンプの間にハイフン (-) を使用します。キーワード \fBnow\fR は、現在の日時の別名として使用できます。指定されたタイムスタンプに、重複したタイムスタンプまたは重複する日付範囲が含まれる場合、重複した各履歴イベントの 1 つのインスタンスのみが出力されます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
 .ad
 .sp .6
 .RS 4n
-該当するイメージのコマンド履歴を表示します。
-.sp
-\fB-H\fR を指定すると、一覧表示からヘッダーを省略します。
-.sp
-\fB-t\fR を指定すると、\fB%Y-%m-%dT%H:%M:%S\fR 形式のタイムスタンプのコンマ区切りリストでログレコードを表示します (\fB strftime\fR(3C) を参照)。日時の範囲を指定するには、開始と終了のタイムスタンプの間にハイフン (-) を使用します。キーワード \fBnow\fR は、現在の日時の別名として使用できます。指定されたタイムスタンプに、重複したタイムスタンプまたは重複する日付範囲が含まれる場合、重複した各履歴イベントの 1 つのインスタンスのみが出力されます。
-.sp
-\fB-l\fR を指定すると、長い形式でログレコードを表示します。これには標準形式に加えて、コマンドの結果、コマンドが完了した日時、使用されたクライアントのバージョンと名前、操作を実行したユーザーの名前、およびコマンドの実行中に発生したすべてのエラーが含まれます。
-.sp
-\fB-n\fR は、最新のものから順に指定された数のエントリのみを表示します。
-.sp
-\fB-o\fR は、列名を指定するコンマ区切りリストを使用して出力を表示します。有効な列名は次のとおりです。
+長い形式でログレコードを表示します。これには標準形式に加えて、コマンドの結果、コマンドが完了した日時、使用されたクライアントのバージョンと名前、操作を実行したユーザーの名前、およびコマンドの実行中に発生したすべてのエラーが含まれます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-N\fR\fR
+.ad
+.sp .6
+.RS 4n
+リリースノートのテキストを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR \fInumber\fR\fR
+.ad
+.sp .6
+.RS 4n
+最新のものから順に指定された数のエントリのみを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIcolumn\fR\fR
+.ad
+.sp .6
+.RS 4n
+列名を指定するコンマ区切りリストを使用して出力を表示します。有効な列名は次のとおりです。
 .sp
 .ne 2
 .mk
 .na
 \fB\fBbe\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作が開始されたブート環境の名前。
 .RE
 
@@ -1037,8 +2330,8 @@
 .na
 \fB\fBbe_uuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作が開始されたブート環境の \fBUUID\fR。
 .RE
 
@@ -1048,8 +2341,8 @@
 .na
 \fB\fBclient\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 クライアントの名前。
 .RE
 
@@ -1059,8 +2352,8 @@
 .na
 \fB\fBclient_ver\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 クライアントのバージョン。
 .RE
 
@@ -1070,8 +2363,8 @@
 .na
 \fB\fBcommand\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作のために使用されたコマンド行。
 .RE
 
@@ -1081,8 +2374,8 @@
 .na
 \fB\fBfinish\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作が完了した日時。
 .RE
 
@@ -1092,8 +2385,8 @@
 .na
 \fB\fBid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作を開始したユーザー ID。
 .RE
 
@@ -1103,8 +2396,8 @@
 .na
 \fB\fBnew_be\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作によって作成された新しいブート環境。
 .RE
 
@@ -1114,8 +2407,8 @@
 .na
 \fB\fBnew_be_uuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作によって作成された新しいブート環境の \fBUUID\fR。
 .RE
 
@@ -1125,8 +2418,8 @@
 .na
 \fB\fBoperation\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 操作の名前。
 .RE
 
@@ -1136,9 +2429,9 @@
 .na
 \fB\fBoutcome\fR\fR
 .ad
-.RS 15n
-.rt  
-この操作の結果の要約。
+.sp .6
+.RS 4n
+この操作の結果のサマリー。
 .RE
 
 .sp
@@ -1147,8 +2440,8 @@
 .na
 \fB\fBreason\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作の結果に関する追加情報。
 .RE
 
@@ -1156,10 +2449,21 @@
 .ne 2
 .mk
 .na
+\fB\fBrelease_note\fR\fR
+.ad
+.sp .6
+.RS 4n
+この操作によってリリースノートが生成されたかどうかを示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBsnapshot\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作中に作成されたスナップショット。これは、操作が正常に完了したあとにスナップショットが自動削除されなかった場合にのみ記録されます。
 .RE
 
@@ -1169,8 +2473,8 @@
 .na
 \fB\fBstart\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作が開始した日時。
 .RE
 
@@ -1180,8 +2484,8 @@
 .na
 \fB\fBtime\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作の実行にかかった合計時間。1 秒未満の操作については 0:00:00 と表示されます。
 .RE
 
@@ -1189,10 +2493,10 @@
 .ne 2
 .mk
 .na
-\fB\fBuser\fR\fR
+\fB\fBuser\fR \fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 この操作を開始したユーザー名。
 .RE
 
@@ -1203,11 +2507,13 @@
 \fBbe\fR および \fBnew_be\fR の値は、\fBbe_uuid\fR または \fBnew_be_uuid\fR フィールドを使用して現在のブート環境名を検索することによって取得されます。その後、ブート環境の名前が変更されたあとにその環境が削除された場合、\fBbe\fR および \fBnew_be\fR に表示される値は、\fBpkg\fR 操作の時点で記録された値です。
 .RE
 
+.RE
+
 .sp
 .ne 2
 .mk
 .na
-\fB\fBpurge-history\fR\fR
+\fB\fBpkg purge-history\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1218,7 +2524,7 @@
 .ne 2
 .mk
 .na
-\fB\fBrebuild-index\fR\fR
+\fB\fBpkg rebuild-index\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1229,7 +2535,7 @@
 .ne 2
 .mk
 .na
-\fB\fBupdate-format\fR\fR
+\fB\fBpkg update-format\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1240,22 +2546,33 @@
 .ne 2
 .mk
 .na
-\fB\fBversion\fR\fR
+\fB\fBpkg version\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fBpkg\fR(1) のバージョンを識別する一意な文字列を表示します。この文字列は、バージョン間で何らかの方法で比較可能であることは保証されていません。
+\fBpkg\fR のバージョンを識別する一意な文字列を表示します。この文字列は、バージョン間で何らかの方法で比較可能であることは保証されていません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBimage-create [\fB-FPUfz\fR] [\fB--force \fR] [\fB--full\fR | \fB--partial\fR | \fB--user\fR] [\fB--zone\fR] [\fB-k\fR \fIssl_key\fR] [\fB-c\fR \fIssl_cert\fR] [\fB--no-refresh\fR] [\fB--variant\fR \fIvariant_spec\fR=\fIinstance \fR ...] [\fB-g\fR \fIpath_or_uri\fR | \fB- -origin\fR \fIpath_or_uri\fR ...] [\fB-m\fR \fI uri\fR | \fB--mirror\fR \fIuri\fR ...] [\fB--facet\fR \fIfacet_spec\fR=(True|False) ...] [(\fB-p\fR | \fB--publisher\fR) [\fIname\fR=]\fI repo_uri\fR] \fIdir\fR\fR\fR
+\fB\fBpkg image-create\fR [\fB-FPUz\fR] [\fB-f\fR |\fB--force\fR] [\fB--full\fR | \fB--partial \fR | \fB--user\fR] [\fB--zone\fR] [\fB-k\fR \fI ssl_key\fR] [\fB-c\fR \fIssl_cert\fR] [\fB--no-refresh\fR] [\fB--variant\fR \fIvariant_name \fR=\fIvalue\fR ...] [\fB-g\fR \fI path_or_uri\fR | \fB--origin\fR \fIpath_or_uri\fR ...] [\fB-m\fR \fIuri\fR | \fB--mirror\fR \fI uri\fR ...] [\fB--set-property\fR \fIname_of_property \fR=\fIvalue\fR] [\fB--facet\fR \fI facet_name\fR=(\fBTrue\fR|\fBFalse\fR) ...] [(\fB-p\fR | \fB--publisher\fR) [\fIname\fR=]\fI repo_uri\fR] \fIdir\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fIdir\fR によって指定された場所に、パッケージ操作に適したイメージを作成します。デフォルトのイメージタイプはユーザーであり、\fB-U\fR (\fB--user\fR) オプションによって指定されます。イメージタイプはフルイメージ (\fB--F\fR または \fB--full\fR)、または指定された \fIdir\fR パスを包含するフルイメージにリンクされた部分イメージ (\fB-P\fR または \fB--partial\fR) に設定できます。\fB-g\fR または \fB--origin\fR を使用して追加の起点を指定できます。\fB--m\fR または \fB--mirror\fR を使用して追加のミラーを指定できます。
+\fIdir\fR によって指定された場所に、パッケージ操作に適したイメージを作成します。デフォルトのイメージタイプはユーザーであり、\fB-U\fR (\fB--user\fR) オプションによって指定されます。イメージタイプはフルイメージ (\fB--F\fR または \fB--full\fR)、または指定された \fIdir\fR パスを包含するフルイメージにリンクされた部分イメージ (\fB-P\fR または \fB--partial\fR) に設定できます。\fB-g\fR または \fB--origin\fR を使用して追加の起点を指定できます。\fB-m\fR または \fB--mirror\fR を使用して追加のミラーを指定できます。
 .sp
 パッケージリポジトリの URI は、\fB-p\fR または \fB--publisher\fR オプションを使用して提供する必要があります。パブリッシャーの名前も提供した場合、イメージの作成時にそのパブリッシャーのみが追加されます。パブリッシャーの名前を提供しない場合、指定されたリポジトリによって認識されているすべてのパブリッシャーがイメージに追加されます。このパブリッシャーに関連付けられたカタログは、初期作成操作に続いて取得が試みられます。
 .sp
@@ -1263,19 +2580,70 @@
 .sp
 イメージが非大域ゾーンコンテキストの内部で実行される予定の場合、\fB-z\fR (\fB--zone\fR) オプションを使用して適切なバリアントを設定できます。
 .sp
-\fB-f\fR (\fB--force\fR) を指定すると、強制的に既存のイメージを上書きしてイメージを作成します。このオプションは慎重に使用してください。
-.sp
-\fB--no-refresh\fR を指定すると、入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージのパブリッシャー用のリポジトリへのアクセスを試みません。
-.sp
-\fB--variant\fR は、指定されたバリアントを指定された値に設定します。
-.sp
-\fB--facet\fR は、指定されたファセットを指定された値に設定します。
+.ne 2
+.mk
+.na
+\fB\fB-f\fR\fR
+.ad
+.br
+.na
+\fB\fB--force\fR\fR
+.ad
+.sp .6
+.RS 4n
+既存のイメージ上にイメージを強制的に作成します。このオプションは慎重に使用してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+入手可能パッケージやその他のメタデータの最新リストを取得するために、イメージの発行元用のリポジトリへのアクセスを試みません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--variant\fR \fIvariant_name\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたバリアントを指定された値に設定します。バリアントの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--facet\fR \fIfacet_name\fR=(\fB True\fR|\fBFalse\fR)\fR
+.ad
+.sp .6
+.RS 4n
+指定されたファセットを指定された値に設定します。ファセットの詳細については、\fBpkg\fR(5) のマニュアルページのファセットとバリアントに関する項目を参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--set-property\fR \fIname_of_property\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたイメージプロパティーを指定された値に設定します。イメージプロパティーの説明については、下の「イメージプロパティー」を参照してください。
+.RE
+
 .RE
 
 .SH イメージプロパティー
 .sp
 .LP
-次のプロパティーはイメージの一部であり、\fBset-property\fR サブコマンドを使用して設定できます。これらのプロパティーの値は、\fBproperty\fR サブコマンドを使用して参照できます。
+次のプロパティーはイメージの特性を定義します。これらのプロパティーは、イメージの目的、内容、および動作に関する情報を格納します。イメージ内のこれらのプロパティーの現在の値を表示するには、\fBpkg property\fR コマンドを使用します。これらのプロパティーの値を変更するには、\fBpkg set-property\fR コマンドおよび \fBpkg unset-property\fR コマンドを使用します。
 .sp
 .ne 2
 .mk
@@ -1291,9 +2659,9 @@
 .na
 \fB\fBdefault\fR\fR
 .ad
-.RS 14n
-.rt  
-デフォルトの BE 作成ポリシー \fBcreate-backup\fR を適用します。
+.sp .6
+.RS 4n
+デフォルトブート環境作成ポリシー \fBcreate-backup\fR を適用します。
 .RE
 
 .sp
@@ -1302,9 +2670,9 @@
 .na
 \fB\fBalways-new\fR\fR
 .ad
-.RS 14n
-.rt  
-次のブート時にアクティブに設定されている新しい BE でパッケージ操作を実行するため、すべてのパッケージ操作に対してリブートを必要とします。明示的に要求されないかぎり、バックアップ BE は作成されません。
+.sp .6
+.RS 4n
+次のブート時にアクティブに設定されている新しいブート環境でパッケージ操作を実行するため、すべてのパッケージ操作に対してリブートを必要とします。明示的にリクエストされないかぎり、バックアップブート環境は作成されません。
 .sp
 このポリシーはもっとも安全ですが、リブートしないとパッケージを追加できないため、ほとんどのサイトの要求よりも厳格です。
 .RE
@@ -1319,7 +2687,7 @@
 .ad
 .sp .6
 .RS 4n
-リブートを必要とするパッケージ操作で、新しい BE が作成され、次のブート時にアクティブに設定されます。パッケージが変更されるか、カーネルに影響する可能性のあるコンテンツがインストールされて操作がライブ BE に影響する場合、バックアップ BE は作成されますがアクティブには設定されません。バックアップ BE を明示的に要求することもできます。
+リブートを必要とするパッケージ操作で、新しいブート環境が作成され、次のブート時にアクティブに設定されます。パッケージが変更されるか、カーネルに影響を及ぼす可能性のある内容がインストールされて、ライブブート環境がこの操作の影響を受ける場合、バックアップブート環境は作成されますが、アクティブには設定されません。バックアップブート環境を明示的にリクエストすることもできます。
 .sp
 このポリシーは、新しくインストールされたソフトウェアによりシステムが不安定になっている場合にのみ潜在的に危険です。この可能性はありますが、比較的まれです。
 .RE
@@ -1332,9 +2700,9 @@
 .ad
 .sp .6
 .RS 4n
-リブートを必要とするパッケージ操作で、新しい BE が作成され、次のブート時にアクティブに設定されます。明示的に要求されないかぎり、バックアップ BE は作成されません。
-.sp
-パッケージの変更によりライブ BE へのこれ以上の変更が不可能になると、フォールバックできる新しい BE がなくなる可能性があるため、このポリシーはもっとも大きな危険を伴います。
+リブートを必要とするパッケージ操作で、新しいブート環境が作成され、次のブート時にアクティブに設定されます。明示的にリクエストされないかぎり、バックアップブート環境は作成されません。
+.sp
+ライブブート環境へのパッケージ変更によりそれ以上の変更が不可能になる場合、フォールバック可能な最近のブート環境が存在しない可能性があるため、このポリシーには最大の危険が伴います。
 .RE
 
 .sp
@@ -1358,7 +2726,7 @@
 .ad
 .sp .6
 .RS 4n
-(文字列) True に設定すると、パッケージクライアントは、署名検証のために使用される証明書の CRL 配布ポイントへのアクセスを試み、発行時よりもあとに証明書が失効していないかどうかを調べます。
+(ブール型) \fBTrue\fR に設定されている場合、パッケージクライアントは、署名検証のために使用される証明書の CRL 配布ポイントへのアクセスを試み、発行時よりもあとに証明書が失効していないかどうかを調べます。
 .sp
 デフォルト値: \fBFalse\fR
 .RE
@@ -1371,7 +2739,7 @@
 .ad
 .sp .6
 .RS 4n
-(ブール型) True に設定すると、パッケージクライアントは、インストールまたは更新操作の完了時にその内容キャッシュ内のファイルを削除します。更新操作の場合、内容はソース BE からのみ削除されます。出力先 BE でパッケージ操作が次に発生したとき、このオプションが変更されていなければ、パッケージクライアントはその内容キャッシュをフラッシュします。
+(ブール型) \fBTrue\fR に設定されている場合、パッケージクライアントは、インストールまたは更新操作の完了時にその内容キャッシュ内のファイルを削除します。更新操作の場合、内容はソースブート環境からのみ削除されます。出力先ブート環境でパッケージ操作が次に発生したとき、このオプションが変更されていなければ、パッケージクライアントはその内容キャッシュをフラッシュします。
 .sp
 このプロパティーを使用して、ディスク容量の限られたシステムで内容キャッシュを小さく保つことができます。このプロパティーを使用すると、操作が完了するまでの時間が長くなる可能性があります。
 .sp
@@ -1386,7 +2754,7 @@
 .ad
 .sp .6
 .RS 4n
-(ブール型) このプロパティーは、mDNS および DNS-SD を使用してリンクローカル内容ミラーを検出するようにクライアントに命令します。このプロパティーを True に設定すると、クライアントはミラーを動的に検出し、そのミラーからパッケージ内容のダウンロードを試みます。mDNS を介してその内容を通知するミラーの実行方法については、\fBpkg.depotd\fR(1M) を参照してください。
+(ブール型) このプロパティーは、mDNS および DNS-SD を使用してリンクローカル内容ミラーを検出するようにクライアントに命令します。このプロパティーを \fBTrue\fR に設定すると、クライアントはミラーを動的に検出し、そのミラーからパッケージ内容のダウンロードを試みます。mDNS を介してその内容を通知するミラーの実行方法については、\fBpkg.depotd\fR(1M) のマニュアルページを参照してください。
 .sp
 デフォルト値: \fBFalse\fR
 .RE
@@ -1412,15 +2780,15 @@
 .ad
 .sp .6
 .RS 4n
-(文字列) イメージ内のパッケージのインストール、更新、修正、または検証時にマニフェストに対してどのチェックが実行されるかを決定します。パッケージに適用される最終的なポリシーは、イメージポリシーとパブリッシャーポリシーの組み合わせに依存します。この組み合わせの厳格さは、少なくとも、この 2 つのポリシーが個別に適用された場合の厳格な方と同じです。デフォルトでは、パッケージクライアントは証明書が失効済みかどうかをチェックしません。そのようなチェック (クライアントから外部 Web サイトへのアクセスが必要な場合がある) を有効にするには、\fBcheck-certificate-revocation\fR イメージプロパティーを \fBtrue\fR に設定します。次の値が許可されます。
+(文字列) イメージ内のパッケージのインストール、更新、修正、または検証時にマニフェストに対してどのチェックが実行されるかを決定します。パッケージに適用される最終的なポリシーは、イメージポリシーと発行元ポリシーの組み合わせに依存します。この組み合わせの厳格さは、少なくとも、この 2 つのポリシーが個別に適用された場合の厳格な方と同じです。デフォルトでは、パッケージクライアントは証明書が失効済みかどうかをチェックしません。そのようなチェック (クライアントから外部 Web サイトへのアクセスが必要な場合がある) を有効にするには、\fBcheck-certificate-revocation\fR イメージプロパティーを \fBTrue\fR に設定します。次の値が許可されます。
 .sp
 .ne 2
 .mk
 .na
 \fB\fBignore\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 すべてのマニフェストの署名を無視します。
 .RE
 
@@ -1430,8 +2798,8 @@
 .na
 \fB\fBverify\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 署名が含まれているすべてのマニフェストが有効に署名されていることを確認しますが、インストール済みパッケージがすべて署名されている必要はありません。これがデフォルト値です。
 .RE
 
@@ -1441,8 +2809,8 @@
 .na
 \fB\fBrequire-signatures\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 新しくインストールされたすべてのパッケージに、有効な署名が少なくとも 1 つ含まれている必要があります。インストール済みパッケージに有効な署名が含まれていない場合は、\fBpkg fix\fR および \fBpkg verify\fR コマンドでも警告が表示されます。
 .RE
 
@@ -1452,8 +2820,8 @@
 .na
 \fB\fBrequire-names\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 \fBrequire-signatures\fR と同じ要件に従いますが、\fBsignature-required-names\fR プロパティーで一覧表示される文字列が、署名の信頼のチェーンを検証するために使用される証明書の共通名としても表示される必要があります。
 .RE
 
@@ -1489,13 +2857,13 @@
 .ad
 .sp .6
 .RS 4n
-(ブール型) このプロパティーではシステムリポジトリを、イメージおよびパブリッシャー構成のソースとして、および提供されたパブリッシャーと通信するためのプロキシとしてイメージで使用するべきかどうかを指定します。デフォルト値は \fBignore\fR です。システムリポジトリについては、\fBpkg.sysrepo\fR(1M) を参照してください。
+(ブール型) このプロパティーではシステムリポジトリを、イメージおよびパブリッシャー構成のソースとして、および提供されたパブリッシャーと通信するためのプロキシとしてイメージで使用するべきかどうかを指定します。デフォルト値は \fBFalse\fR です。システムリポジトリについては、\fBpkg.sysrepo\fR(1M) のマニュアルページを参照してください。
 .RE
 
 .SH パブリッシャープロパティー
 .sp
 .LP
-次のプロパティーはイメージの一部であり、\fBset-publisher\fR サブコマンドの \fB--set-property\fR オプションを使用して設定できます。
+次のプロパティーは、特定の発行元の署名ポリシーを定義します。同じ名前のイメージプロパティーはイメージの署名ポリシーを定義します。特定の発行元のこれらのプロパティーの現在の値を表示するには、\fBpkg publisher\fR \fIpublisher_name\fR コマンドを使用します。これらの発行元の署名ポリシープロパティーの値を変更するには、\fBpkg set-publisher\fR コマンドの \fB--set-property\fR オプションと \fB--unset-property\fR オプションを使用します。
 .sp
 .ne 2
 .mk
@@ -1520,7 +2888,7 @@
 
 .SH 使用例
 .LP
-\fB例 1 \fRパブリッシャーを設定してイメージを作成する
+\fB例 1 \fRパブリッシャーを構成してイメージを作成する
 .sp
 .LP
 パブリッシャーを \fBexample.com\fR として新しいフルイメージを作成し、\fB/aux0/example_root\fR に格納します。
@@ -1553,10 +2921,10 @@
 .sp
 
 .LP
-\fB例 3 \fRパブリッシャーを設定せずにイメージを作成する
+\fB例 3 \fRパブリッシャーを構成せずにイメージを作成する
 .sp
 .LP
-パブリッシャーを設定せずに、新しいフルイメージを \fB/aux0/example_root\fR に作成します。
+パブリッシャーを構成せずに、新しいフルイメージを \fB/aux0/example_root\fR に作成します。
 
 .sp
 .in +2
@@ -1567,7 +2935,7 @@
 .sp
 
 .LP
-\fB例 4 \fRパッケージをインストールする
+\fB例 4 \fRパッケージのインストール
 .sp
 .LP
 \fBwidget\fR パッケージの最新バージョンを現在のイメージにインストールします。
@@ -1642,11 +3010,13 @@
 .in +2
 .nf
 $ \fBpkg search bge\fR
-INDEX       ACTION VALUE                      PACKAGE
-driver_name driver bge                        pkg:/driver/network/[email protected]
-basename    file   kernel/drv/sparcv9/bge     pkg:/driver/network/[email protected]
-basename    file   kernel/drv/amd64/bge       pkg:/driver/network/[email protected]
-pkg.fmri    set    solaris/driver/network/bge pkg:/driver/network/[email protected]
+INDEX       ACTION VALUE                                 PACKAGE
+driver_name driver bge                                   pkg:/driver/network/ethernet/[email protected]
+basename    file   kernel/drv/sparcv9/bge                pkg:/driver/network/ethernet/[email protected]
+basename    file   kernel/drv/amd64/bge                  pkg:/driver/network/ethernet/[email protected]
+basename    file   platform/sun4v/kernel/drv/sparcv9/bge pkg:/system/kernel/[email protected]
+pkg.fmri    set    solaris/driver/network/bge            pkg:/driver/network/[email protected]
+pkg.fmri    set    solaris/driver/network/ethernet/bge   pkg:/driver/network/ethernet/[email protected]
 .fi
 .in -2
 .sp
@@ -1656,7 +3026,89 @@
 このトークンはパッケージ \fBdriver/network/bge\fR 内に、\fB/kernel/drv/\fI arch\fR/bge\fR を表すファイルアクションのベース名として、およびドライバ名として存在します。
 
 .LP
-\fB例 8 \fR指定されたパッケージに依存するパッケージを検索する
+\fB例 8 \fRファイルの検索
+.sp
+.LP
+先頭のスラッシュ文字を含むファイルのフルパス名を指定して、ファイルを提供するパッケージを検索します。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l /usr/bin/vim\fR
+PATH         PKG.NAME
+usr/bin/vim  editor/vim/vim-core
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+\fIaction_name\fR に \fB file\fR を指定し、\fIindex\fR に \fBpath\fR または \fBbasename\fR を指定し、\fItoken\fR に完全または部分的なファイル名を指定することにより、ファイルおよびそのファイルを提供するパッケージを検索します。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l file:basename:vim\fR
+PATH         PKG.NAME
+usr/bin/vim  editor/vim/vim-core
+.fi
+.in -2
+.sp
+
+.LP
+\fB例 9 \fRファイルとディレクトリの検索
+.sp
+.LP
+\fI index\fR に \fBpath\fR または \fBbasename\fR を、\fItoken\fR に完全または部分的なファイル名を指定することにより、ファイルとディレクトリ、およびそれらを提供するパッケージを検索します。使用するシェルによっては、ワイルドカードをエスケープする必要があります。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l path:*/vim\fR
+PATH           PKG.NAME
+usr/bin/vim    editor/vim/vim-core
+usr/share/vim  editor/vim
+usr/share/vim  editor/vim/vim-core
+$ \fBpkg search -o path,pkg.name -l basename:vim\fR
+PATH           PKG.NAME
+usr/share/vim  editor/vim
+usr/share/vim  editor/vim/vim-core
+usr/bin/vim    editor/vim/vim-core
+.fi
+.in -2
+.sp
+
+.LP
+\fB例 10 \fRどのパッケージがどの SMF サービスを提供するかを表示する
+.sp
+.LP
+構造化された検索内で \fIindex\fR に値 \fBorg.opensolaris.smf.fmri\fR を指定し、\fI token\fR に検索対象のサービスの名前を指定することにより、特定の SMF サービスを提供するのはどのパッケージかを表示します。値 \fBorg.opensolaris.smf.fmri\fR は、\fBset\fR アクションの属性の名前です。サービスの名前では、「:」を確実にエスケープしてください。
+
+.sp
+.LP
+たとえば、使用可能な HTTP サーバーを表示するには、\fItoken\fR に値 \fBsvc:/network/http\fR を指定します。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search 'org.opensolaris.smf.fmri:svc\e:/network/http*'\fR
+INDEX                    ACTION VALUE                        PACKAGE
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/java-servlet/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:apache22   pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:lighttpd14 pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:privoxy    pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:squid      pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:tomcat6    pkg:/web/java-servlet/[email protected]
+.fi
+.in -2
+.sp
+
+.LP
+\fB例 11 \fR指定されたパッケージに依存するパッケージを検索する
 .sp
 .LP
 \fBpackage/pkg\fR に依存するインストール済みパッケージを検索します。
@@ -1664,17 +3116,23 @@
 .sp
 .in +2
 .nf
-$ \fBpkg search -l 'depend::package/pkg'\fR
-INDEX       ACTION VALUE                    PACKAGE
-incorporate depend package/[email protected] pkg:/consolidation/ips/[email protected]
-require     depend package/[email protected] pkg:/system/[email protected]
-require     depend package/[email protected] pkg:/package/pkg/[email protected]
+$ \fBpkg search -l depend::package/pkg\fR
+INDEX       ACTION VALUE                                    PACKAGE
+incorporate depend package/[email protected]      pkg:/consolidation/ips/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/library/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/library/[email protected]
+require     depend package/pkg                             pkg:/system/zones/brand/[email protected]
+require     depend pkg:/package/[email protected] pkg:/install/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 9 \fR依存関係を検索する
+\fB例 12 \fR依存関係を検索する
 .sp
 .LP
 インストール済みパッケージ内のすべての \fBincorporate\fR 依存関係を検索します。
@@ -1682,17 +3140,17 @@
 .sp
 .in +2
 .nf
-$ \fBpkg search -l 'depend:incorporate:'\fR
-INDEX       ACTION VALUE                           PACKAGE
-incorporate depend pkg:/[email protected],5.11-0.133  pkg:/consolidation/osnet/[email protected]
-incorporate depend pkg:/[email protected],5.11-0.133 pkg:/consolidation/osnet/[email protected]
+$ \fBpkg search -l depend:incorporate:\fR
+INDEX       ACTION VALUE                                PACKAGE
+incorporate depend pkg:/[email protected]  pkg:/consolidation/osnet/[email protected]
+incorporate depend pkg:/[email protected] pkg:/consolidation/osnet/[email protected]
 \&...
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 10 \fRパブリッシャーを追加する
+\fB例 13 \fR発行元を追加
 .sp
 .LP
 新しいパブリッシャー \fBexample.com\fR を追加し、リポジトリの場所を \fBhttp://www.example.com/repo\fR に設定します。
@@ -1706,7 +3164,7 @@
 .sp
 
 .LP
-\fB例 11 \fR鍵と証明書を指定してパブリッシャーを追加する
+\fB例 14 \fR鍵と証明書を指定してパブリッシャーを追加する
 .sp
 .LP
 新しいパブリッシャー \fBexample.com\fR を追加し、セキュリティー保護されたリポジトリの場所を \fBhttps://secure.example.com/repo\fR に設定し、鍵および証明書をディレクトリ \fB/root/creds\fR に格納します。
@@ -1722,7 +3180,7 @@
 .sp
 
 .LP
-\fB例 12 \fRパブリッシャーを追加して自動設定する
+\fB例 15 \fRパブリッシャーを追加して自動構成する
 .sp
 .LP
 自動設定を使用して新しいパブリッシャーを追加し、リポジトリの場所を \fB/export/repo\fR に設定します。
@@ -1736,7 +3194,7 @@
 .sp
 
 .LP
-\fB例 13 \fRパブリッシャーを追加して手動設定する
+\fB例 16 \fRパブリッシャーを追加して手動構成する
 .sp
 .LP
 手動設定を使用して新しいパブリッシャー \fBexample.com\fR を追加し、リポジトリの場所を \fB/export/repo/example.com\fR に設定します。
@@ -1750,10 +3208,25 @@
 .sp
 
 .LP
-\fB例 14 \fRすべての署名付きパッケージを検証する
+\fB例 17 \fR発行元を追加してプロキシを構成する
 .sp
 .LP
-すべての署名付きパッケージを検証するようにイメージを設定します。
+起点 \fBhttp://server/repo \fR とプロキシ \fBhttp://webcache:8080\fR を使用して新しい発行元 \fBmypub\fR を追加します。
+
+.sp
+.in +2
+.nf
+$ \fBpkg set-publisher -g http://server/repo \e\fR
+\fB--proxy http://webcache:8080 mypub\fR
+.fi
+.in -2
+.sp
+
+.LP
+\fB例 18 \fRすべての署名付きパッケージを検証する
+.sp
+.LP
+すべての署名付きパッケージを検証するようにイメージを構成します。
 
 .sp
 .in +2
@@ -1764,10 +3237,10 @@
 .sp
 
 .LP
-\fB例 15 \fRすべてのパッケージで署名を必須にする
+\fB例 19 \fRすべてのパッケージで署名を必須にする
 .sp
 .LP
-すべてのパッケージで署名を必須とするように、また、いずれかの証明書で文字列 \fBexample.com\fR が共通名として信頼チェーンに出現することを必須とするようにイメージを設定します。
+すべてのパッケージで署名を必須とするように、また、いずれかの証明書で文字列 \fBexample.com\fR が共通名として信頼チェーンに出現することを必須とするようにイメージを構成します。
 
 .sp
 .in +2
@@ -1778,10 +3251,10 @@
 .sp
 
 .LP
-\fB例 16 \fR指定したパブリッシャーからのすべてのパッケージで署名を必須にする
+\fB例 20 \fR指定したパブリッシャーからのすべてのパッケージで署名を必須にする
 .sp
 .LP
-パブリッシャー \fBexample.com\fR からインストールされるすべてのパッケージで署名を必須とするようにイメージを設定します。
+パブリッシャー \fBexample.com\fR からインストールされるすべてのパッケージで署名を必須とするようにイメージを構成します。
 
 .sp
 .in +2
@@ -1793,7 +3266,7 @@
 .sp
 
 .LP
-\fB例 17 \fR信頼チェーンで指定された文字列を必須にする
+\fB例 21 \fR信頼チェーンで指定された文字列を必須にする
 .sp
 .LP
 有効とみなされるために署名の信頼チェーンに存在する必要がある文字列 \fBfoo\fR をイメージの共通名の一覧に追加します。
@@ -1807,7 +3280,7 @@
 .sp
 
 .LP
-\fB例 18 \fR指定されたパブリッシャーの信頼チェーンから文字列を削除する
+\fB例 22 \fR指定されたパブリッシャーの信頼チェーンから文字列を削除する
 .sp
 .LP
 パブリッシャー \fBexample.com\fR の署名を検証するために存在する必要がある文字列 \fBfoo\fR を共通名の一覧から削除します。
@@ -1822,7 +3295,7 @@
 .sp
 
 .LP
-\fB例 19 \fR信頼できる CA 証明書を追加する
+\fB例 23 \fR信頼できる CA 証明書を追加する
 .sp
 .LP
 \fB/tmp/example_file.pem\fR に格納された証明書を、パブリッシャー \fBexample.com\fR の信頼できる CA 証明書として追加します。
@@ -1837,7 +3310,7 @@
 .sp
 
 .LP
-\fB例 20 \fR証明書を失効させる
+\fB例 24 \fR証明書を失効させる
 .sp
 .LP
 \fBa12345\fR というハッシュを持つ、パブリッシャー \fBexample.com\fR 用の証明書を失効させ、\fBexample.com\fR からのパッケージの署名をその証明書で検証しないようにします。
@@ -1851,7 +3324,7 @@
 .sp
 
 .LP
-\fB例 21 \fR証明書を抹消する
+\fB例 25 \fR証明書を抹消する
 .sp
 .LP
 証明書 \fBa12345\fR がユーザーによって追加または失効させられたことを \fBpkg\fR から抹消します。
@@ -1865,7 +3338,7 @@
 .sp
 
 .LP
-\fB例 22 \fRパッケージをダウングレードする
+\fB例 26 \fRパッケージをダウングレードする
 .sp
 .LP
 インストール済みパッケージ \[email protected]\fR を古いバージョンにダウングレードします。
@@ -1879,7 +3352,7 @@
 .sp
 
 .LP
-\fB例 23 \fR競合するパッケージインストールを切り替える
+\fB例 27 \fR競合するパッケージインストールを切り替える
 .sp
 .LP
 2 つのパッケージが競合している場合に、どちらのパッケージがインストールされるかを切り替えます。パッケージ A がパッケージ B または C のどちらかに依存し、B および C は相互排他であるとします。A と B がインストールされる場合に、次のコマンドを使用して、A をアンインストールせずに B の代わりに C を使用するように切り替えます。
@@ -1893,7 +3366,7 @@
 .sp
 
 .LP
-\fB例 24 \fRパッケージアーカイブ内のパッケージを一覧表示する
+\fB例 28 \fRパッケージアーカイブ内のパッケージを一覧表示する
 .sp
 .LP
 パッケージアーカイブ内のすべてのパッケージのすべてのバージョンを一覧表示します。
@@ -1907,7 +3380,7 @@
 .sp
 
 .LP
-\fB例 25 \fRパッケージリポジトリ内のパッケージを一覧表示する
+\fB例 29 \fRパッケージリポジトリ内のパッケージを一覧表示する
 .sp
 .LP
 リポジトリ内のすべてのパッケージのすべてのバージョンを一覧表示します。
@@ -1921,7 +3394,7 @@
 .sp
 
 .LP
-\fB例 26 \fRパッケージアーカイブ内のパッケージについての情報を表示する
+\fB例 30 \fRパッケージアーカイブ内のパッケージについての情報を表示する
 .sp
 .LP
 パッケージアーカイブ内のパッケージの最新バージョンのパッケージ情報を表示します。パッケージが現在インストールされていてもいなくてもかまいません。
@@ -1935,7 +3408,7 @@
 .sp
 
 .LP
-\fB例 27 \fRパッケージアーカイブ内のパッケージの内容を表示する
+\fB例 31 \fRパッケージアーカイブ内のパッケージの内容を表示する
 .sp
 .LP
 パッケージアーカイブ内のパッケージの内容を表示します。パッケージは現在インストールされていません。
@@ -1949,7 +3422,7 @@
 .sp
 
 .LP
-\fB例 28 \fRパブリッシャーの起点とミラーをすべて削除する
+\fB例 32 \fRパブリッシャーの起点とミラーをすべて削除する
 .sp
 .LP
 パブリッシャーのすべての起点およびミラーを削除し、新しい起点を追加します。
@@ -1983,7 +3456,9 @@
 .ad
 .sp .6
 .RS 4n
-トランスポート操作中に接続しようとするのを待機する秒数 (試行ごと)。これが経過するとクライアントは操作を中止します。デフォルトの値は 60 です。
+トランスポート操作中に接続しようとするのを待機する秒数 (試行ごと)。これが経過するとクライアントは操作を中止します。値 0 は無制限に待機することを意味します。
+.sp
+デフォルト値: 60
 .RE
 
 .sp
@@ -1994,7 +3469,9 @@
 .ad
 .sp .6
 .RS 4n
-トランスポート操作中に \fBlowspeed\fR 制限 (1024 バイト/秒) を下回っていられる秒数。これが経過するとクライアントは操作を中止します。デフォルトの値は 30 です。
+トランスポート操作中に \fBlowspeed\fR 制限 (1024 バイト/秒) を下回っていられる秒数。これが経過するとクライアントは操作を中止します。値 0 は、操作を中止しないことを意味します。
+.sp
+デフォルト値: 30
 .RE
 
 .sp
@@ -2005,7 +3482,9 @@
 .ad
 .sp .6
 .RS 4n
-一時的なトランスポートエラーの最大数。これを上回るとクライアントは操作を中止します。デフォルト値は 4 です。
+一時的なトランスポートエラーの最大数。これを上回るとクライアントは操作を中止します。値 0 は、操作を中止しないことを意味します。
+.sp
+デフォルト値: 4
 .RE
 
 .sp
@@ -2016,7 +3495,24 @@
 .ad
 .sp .6
 .RS 4n
-トランスポート操作中に許可される HTTP または HTTPS リダイレクトの最大数。これを上回ると接続が中止されます。デフォルト値は 5 です。
+トランスポート操作中に許可される HTTP または HTTPS リダイレクトの最大数。これを上回ると接続が中止されます。値 0 は、操作を中止しないことを意味します。
+.sp
+デフォルト値: 5
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBPKG_CONCURRENCY\fR\fR
+.ad
+.sp .6
+.RS 4n
+同時に更新する子イメージの数。\fB-C\fR オプションが指定されている場合には、無視されます。
+.sp
+子イメージ (通常はゾーン) 内への再帰時に、最大 \fB$PKG_CONCURRENCY \fR 個の子イメージを同時に更新します。\fB$PKG_CONCURRENCY\fR が 0 または負数の場合は、すべての子イメージが同時に更新されます。
+.sp
+デフォルト値: 1
 .RE
 
 .sp
@@ -2027,7 +3523,9 @@
 .ad
 .sp .6
 .RS 4n
-ホストあたりのトランスポート試行の最大数。これを上回るとクライアントは操作を中止します。デフォルト値は 4 です。
+ホストあたりのトランスポート試行の最大数。これを上回るとクライアントは操作を中止します。値 0 は、操作を中止しないことを意味します。
+.sp
+デフォルト値: 4
 .RE
 
 .sp
@@ -2044,7 +3542,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -2064,18 +3562,18 @@
 .ad
 .RS 6n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
@@ -2086,7 +3584,7 @@
 .ad
 .RS 6n
 .rt  
-複数の操作が要求されましたが、そのうちの一部だけが成功しました。
+複数の操作が要求されましたが、それらの一部のみが成功しました。
 .RE
 
 .sp
@@ -2156,7 +3654,7 @@
 .ad
 .sp .6
 .RS 4n
-フルイメージまたは部分イメージのメタデータディレクトリ。
+完全または部分的なイメージのメタデータディレクトリ。
 .RE
 
 .sp
@@ -2179,8 +3677,8 @@
 .na
 \fB\fB$IMAGE_META/lost+found\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 パッケージ操作中に移動された、競合するディレクトリおよびファイルの場所。削除されたディレクトリのパッケージ化されない内容の場所。
 .RE
 
@@ -2190,8 +3688,8 @@
 .na
 \fB\fB$IMAGE_META/publisher\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 パブリッシャーごとに 1 つのディレクトリが含まれます。各ディレクトリにはパブリッシャー固有のメタデータが格納されます。
 .RE
 
@@ -2220,7 +3718,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkgsend\fR(1), \fBpkg.depotd\fR(1M), \fB glob\fR(3C), \fBpkg\fR(5), \fBbeadm\fR(1M)
+\fBpkgsend\fR(1), \fBpkg.depotd\fR(1M), \fBglob\fR(3C), \fBpkg\fR(5), \fBbeadm\fR(1M)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pkg.5	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkg.5	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkg 5 "2011 年 8 月 30 日" "SunOS 5.11" "標準、環境、マクロ"
+.\" Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkg 5 "2012 年 6 月 22 日" "SunOS 5.11" "標準、環境、マクロ"
 .SH 名前
 pkg \- Image Packaging System
 .SH 機能説明
@@ -14,17 +14,17 @@
 .sp
 .in +2
 .nf
-pkg://opensolaris.org/library/[email protected],5.11-0.75:20071001T163427Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z
 .fi
 .in -2
 .sp
 
 .sp
 .LP
-\fBopensolaris.org\fR はパブリッシャーです。\fBlibrary/libc\fR はパッケージ名です。名前空間は階層的であり、その深さは任意ですが、適用される包含関係は存在しません。名前は基本的に任意です。パブリッシャー情報は省略可能ですが、存在する場合は、前に \fBpkg://\fR を付ける必要があります。パブリッシャーを含む FMRI は多くの場合、「完全指定」と呼ばれます。パブリッシャー情報が存在しない場合は、一般に、パッケージ名の前に \fBpkg:/\fR が付けられます。
+\fBsolaris\fR は発行元です。\fBsystem/library/c++-runtime\fR はパッケージ名です。名前空間は階層的であり、その深さは任意ですが、適用される包含関係は存在しません。名前は基本的に任意です。発行元情報はオプションですが、存在する場合は \fBpkg://\fR を前に付ける必要があります。発行元を含む FMRI は多くの場合、「完全指定」と呼ばれます。発行元情報が存在しない場合は一般に、パッケージ名の前に \fBpkg:/\fR が付けられます。
 .sp
 .LP
-クライアントをパッケージ化すると、通常、FMRI にパブリッシャー情報が含まれていない場合に FMRI のスキームを省略できます。たとえば、\fBpkg:/library/libc\fR を \fBlibrary/libc\fR として記述できます。スキームが省略される場合、クライアントは照合の目的で、パッケージ名の最後のコンポーネントを除くすべてのコンポーネントを省略することもできます。たとえば、\fBlibrary/libc\fR を \fBlibc\fR として記述できます。これは、\fBlibc\fR という名前のパッケージ、または \fB/libc\fR で終わるパッケージ名に一致します。
+クライアントをパッケージ化すると、通常、FMRI にパブリッシャー情報が含まれていない場合に FMRI のスキームを省略できます。たとえば、\fBpkg:/system/library/c++-runtime\fR は \fBsystem/library/c++-runtime\fR と書くことができます。スキームが省略される場合、クライアントは照合の目的で、パッケージ名の最後のコンポーネントを除くすべてのコンポーネントを省略することもできます。たとえば、\fBsystem/library/c++-runtime\fR は \fBlibrary/c++-runtime\fR または \fBc++-runtime\fR と書くことができ、これらは \fBc++-runtime\fR という名前のパッケージまたは \fB/c++-runtime\fR で終わるパッケージ名に一致します。
 .sp
 .LP
 パブリッシャーの名前によって、人、人のグループ、または組織が 1 つ以上のパッケージのソースとして識別されます。パブリッシャーの名前の競合を避け、パブリッシャーを識別しやすくするために、パッケージを公開するエンティティーを表すドメイン名をパブリッシャーの名前として使用することがベストプラクティスです。
@@ -52,7 +52,7 @@
 .SH アクション
 .sp
 .LP
-アクションは、システム上のインストール可能オブジェクトを表します。アクションは、パッケージのマニフェスト内に記述されます。すべてのアクションは、最初に名前とキー属性を含みます。また、これらはバージョン履歴をたどる過程で一意のオブジェクトを参照します。アクションには、このほかの属性も含まれます。一部の属性は、パッケージシステムによって直接解釈されます。その他の属性は、システム管理者またはエンドユーザーにのみ役立つ可能性があります。
+アクションはシステム上のインストール可能オブジェクトを表します。アクションはパッケージのマニフェストに記述されます。すべてのアクションは、最初に名前とキー属性を含みます。また、これらはバージョン履歴をたどる過程で一意のオブジェクトを参照します。アクションには、このほかの属性も含まれます。一部の属性は、パッケージシステムによって直接解釈されます。その他の属性は、システム管理者またはエンドユーザーにのみ役立つ可能性があります。
 .sp
 .LP
 アクションには、次の単純なテキスト表現があります。
@@ -65,7 +65,7 @@
 
 .sp
 .LP
-属性の名前に、空白、引用符、または等号 (=) を含めることはできません。最初の等号のあとの文字はすべて、値に属します。値にはすべての文字を含めることができますが、スペースは単一引用符または二重引用符で囲む必要があります。二重引用符で囲まれている文字列の内部で単一引用符をエスケープする必要はなく、単一引用符で囲まれている文字列の内部で二重引用符をエスケープする必要はありません。引用符の前にバックスラッシュ (\\) 文字を付けて、引用文字列が終了しないようにすることができます。バックスラッシュは、バックスラッシュでエスケープできます。
+属性の名前に、空白、引用符、または等号 (=) を含めることはできません。最初の等号のあとの文字はすべて、値に属します。値にはすべての文字を含めることができますが、スペースは単一引用符または二重引用符で囲む必要があります。二重引用符で囲まれている文字列の内部で単一引用符をエスケープする必要はなく、単一引用符で囲まれている文字列の内部で二重引用符をエスケープする必要はありません。引用符の前にバックスラッシュ (\) 文字を付けて、引用文字列が終了しないようにすることができます。バックスラッシュは、バックスラッシュでエスケープできます。
 .sp
 .LP
 複数の値を使用して、属性に複数回名前を付けることができます。これらは、順序なしリストとして扱われます。
@@ -77,7 +77,7 @@
 下に示されている属性セットは、これがすべてではありません。実際、アクションに付加できる属性は任意であるため、標準の属性セットは、将来の開発を実装するために容易に拡張できます。
 .sp
 .LP
-特定のアクション属性によって、パッケージ化コンテキストの外部で追加の操作が実行されます。これらの属性は、下の「アクチュエータ」の節で説明されています。
+特定のアクション属性によって、パッケージ化コンテキストの外部で追加の操作が実行されます。これらの属性は、下の「アクチュエータ」のセクションで説明されています。
 .SS "ファイルアクション"
 .sp
 .LP
@@ -138,8 +138,8 @@
 .na
 \fB\fBpreserve\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 これは、ファイルの内容がそのファイルのインストールまたは最後のアップグレード以降に変更されたと判定された場合、アップグレード時にその内容を上書きすべきではないことを指定します。初期インストール時に既存のファイルが見つかった場合、そのファイルは回収されます (\fB/var/pkg/lost+found\fR 内に格納されます)。
 .sp
 \fBpreserve\fR の値が \fBrenameold\fR である場合は、既存のファイルの名前が拡張子 \fB\&.old\fR を使用して変更され、新しいファイルがその場所に置かれます。
@@ -157,8 +157,8 @@
 .na
 \fB\fBoverlay\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 これは、このアクションによってほかのパッケージが同じ場所にファイルを提供できるか、またはこのアクションによって別のファイルをオーバーレイすることを目的にしたファイルが提供されるかを指定します。この機能は、どの自己アセンブリにも参加しておらず (たとえば、\fB/etc/motd\fR)、かつ安全に上書きできる構成ファイルで使用されることを目的にしています。
 .sp
 \fBoverlay\fR が指定されていない場合は、複数のパッケージが同じ場所にファイルを提供することはできません。
@@ -177,8 +177,8 @@
 .na
 \fB\fBelfarch\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 ELF ファイルのアーキテクチャー。これは、そのファイルが構築されたアーキテクチャー上での \fBuname -p\fR の出力です。
 .RE
 
@@ -188,8 +188,8 @@
 .na
 \fB\fBelfbits\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 これは \fB32\fR または \fB64\fR です。
 .RE
 
@@ -199,8 +199,8 @@
 .na
 \fB\fBelfhash\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 これは、そのファイル内の「興味深い」ELF セクションのハッシュです。これらは、バイナリがロードされるときにメモリーにマップされるセクションです。これらは、2 つのバイナリの実行可能ファイルの動作が異なるかどうかを判定するときに考慮する必要のある唯一のセクションです。
 .RE
 
@@ -210,8 +210,8 @@
 .na
 \fB\fBoriginal_name\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 この属性は、パッケージからパッケージに、または場所から場所に、あるいはその両方で移動している編集可能なファイルを処理するために使用されます。この形式は、元のパッケージの名前のあとに、コロンとこのファイルの元のパスが続きます。削除されているファイルはすべて、そのパッケージとパス、または \fBoriginal_name\fR 属性の値 (指定されている場合) のどちらかを使用して記録されます。\fBoriginal_name\fR 属性が設定された、インストールされている編集可能なファイルはすべて、それが同じパッケージ化の操作の一部として削除されている場合は、その名前のファイルを使用します。
 .RE
 
@@ -219,11 +219,22 @@
 .ne 2
 .mk
 .na
+\fB\fBrelease-note\fR\fR
+.ad
+.sp .6
+.RS 4n
+この属性は、このファイルにリリースノートテキストが含まれていることを示すために使用されます。この属性の値は、パッケージ FMRI です。元のイメージに存在し、元のイメージ内のパッケージよりも新しいバージョンのパッケージ名が FMRI で指定されている場合、このファイルはリリースノートに含まれます。特別な FMRI (\fBfeature/pkg/self\fR) は、含まれるパッケージを指します。\fBfeature/pkg/self\fR のバージョンが 0 の場合、このファイルは初期インストールのリリースノートにのみ含まれます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBrevert-tag\fR\fR
 .ad
-.RS 17n
-.rt  
-この属性は、セットとして元に戻すべき編集可能なファイルをタグ付けするために使用されます。複数の revert-tag 値を指定できます。これらのいずれかのタグを指定して \fBpkg revert\fR が呼び出されると、ファイルはマニフェストで定義された状態に戻ります。\fBpkg\fR(1) を参照してください。
+.sp .6
+.RS 4n
+この属性は、セットとして元に戻すべき編集可能なファイルをタグ付けするために使用されます。複数の \fBrevert-tag\fR 値を指定できます。これらのいずれかのタグを指定して \fBpkg revert\fR が呼び出されると、ファイルはマニフェストで定義された状態に戻ります。\fBpkg\fR(1) を参照してください。
 .RE
 
 .SS "ディレクトリアクション"
@@ -232,7 +243,7 @@
 \fBdir\fR アクションは、ファイルシステムオブジェクトを表すという点で \fBfile\fR アクションに似ています。\fBdir\fR アクションは、通常ファイルの代わりにディレクトリを表します。\fBdir\fR アクションには、\fBfile\fR アクションと同じ 4 つの標準属性があり、\fBpath\fR がキー属性です。
 .sp
 .LP
-ディレクトリは、IPS でカウントされる参照です。あるディレクトリを明示的または暗黙的に参照している最後のパッケージが参照を行わなくなると、そのディレクトリは削除されます。そのディレクトリにパッケージ解除されたファイルシステムオブジェクトが含まれている場合、それらの項目は \fB$IMAGE_META/lost+found\fR に移動されます。\fB$IMAGE_META\fR についての詳細は、「ファイル」の節を参照してください。
+ディレクトリは、IPS でカウントされる参照です。あるディレクトリを明示的または暗黙的に参照している最後のパッケージが参照を行わなくなると、そのディレクトリは削除されます。そのディレクトリにパッケージ解除されたファイルシステムオブジェクトが含まれている場合、それらの項目は \fB$IMAGE_META/lost+found\fR に移動されます。\fB$IMAGE_META\fR についての詳細は、「ファイル」のセクションを参照してください。
 .sp
 .LP
 パッケージ解除された内容を新しいディレクトリに移動するために、次の属性が役立つことがあります。
@@ -242,8 +253,8 @@
 .na
 \fB\fBsalvage-from\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 これは、回収された項目のディレクトリを指定します。このような属性を持つディレクトリは、作成時、回収されたディレクトリの内容を継承します (その内容が存在する場合)。
 .RE
 
@@ -266,7 +277,7 @@
 .ne 2
 .mk
 .na
-\fB\fBtarget\fR\fR
+\fB\fBtarget\fR \fR
 .ad
 .sp .6
 .RS 4n
@@ -307,7 +318,7 @@
 .sp
 この値は、英数字とスペースで構成された任意の長さの文字列にすることができます。実装自体をバージョン管理できるか、または実際にバージョン管理されている場合は、文字列の最後の @ のあとに (負にならない整数のドットで区切られた並びとして表された) バージョンを指定します。実装の複数のバージョンが存在する場合、デフォルトの動作では、最大のバージョンを持つ実装が選択されます。
 .sp
-特定のパスにある実装メディエーションリンクの 1 つのインスタンスだけがシステムにインストールされている場合は、その 1 つのインスタンスが自動的に選択されます。このパスにある将来のリンクがインストールされても、ベンダー、サイト、またはローカルの上書きが適用されないかぎり、またはいずれかのリンクのバージョンがメディエートされた場合、このリンクは切り替えられません。
+特定のパスにある実装メディエーションリンクの 1 つのインスタンスだけがシステムにインストールされている場合は、その 1 つのインスタンスが自動的に選択されます。このパスにある将来のリンクがインストールされても、ベンダー、サイト、またはローカルのオーバーライドが適用されないかぎり、またはいずれかのリンクのバージョンがメディエートされた場合、このリンクは切り替えられません。
 .RE
 
 .sp
@@ -318,7 +329,7 @@
 .ad
 .sp .6
 .RS 4n
-メディエートされたリンクの競合を解決する場合、\fBpkg\fR(5) は通常、\fBmediator-version\fR の最大の値を持つリンクを選択するか、またはそれが不可能な場合は \fBmediator-implementation\fR に基づいて選択します。この属性は、正常な競合解決処理のための上書きを指定するために使用されます。
+メディエートされたリンクの競合を解決する場合、\fBpkg\fR(5) は通常、\fBmediator-version\fR の最大の値を持つリンクを選択するか、またはそれが不可能な場合は \fBmediator-implementation\fR に基づいて選択します。この属性は、正常な競合解決処理のためのオーバーライドを指定するために使用されます。
 .sp
 この属性が指定されていない場合は、デフォルトのメディエータ選択ロジックが適用されます。
 .sp
@@ -326,7 +337,7 @@
 .sp
 この値が \fBsite\fR である場合は、このリンクが、\fBvendor\fR の値を持つリンクや、\fBmediator-priority\fR が指定されていないリンクより優先されます。
 .sp
-ローカルシステム管理者は、上で説明した選択ロジックを上書きできます。
+ローカルシステム管理者は、上で説明した選択ロジックをオーバーライドできます。
 .RE
 
 .SS "ハードリンクアクション"
@@ -341,10 +352,10 @@
 .ne 2
 .mk
 .na
-\fB\fBname\fR \fR
+\fB\fBname\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ドライバの名前。多くの場合はドライババイナリのファイル名ですが、必ずしもそうとは限りません。これは \fBdriver\fR アクションのキー属性です。
 .RE
 
@@ -354,8 +365,8 @@
 .na
 \fB\fBalias\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これはドライバの別名を表します。特定のドライバが複数の \fBalias\fR 属性を持つことができます。特殊な引用符の規則は必要ありません。
 .RE
 
@@ -365,8 +376,8 @@
 .na
 \fB\fBclass\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これはドライバクラスを表します。特定のドライバが複数の \fBclass\fR 属性を持つことができます。
 .RE
 
@@ -376,8 +387,8 @@
 .na
 \fB\fBperms\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これは、ドライバのデバイスノードのファイルシステムアクセス権を表します。
 .RE
 
@@ -387,8 +398,8 @@
 .na
 \fB\fBclone_perms\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これは、このドライバに対する複製ドライバのマイナーノードのファイルシステムアクセス権を表します。
 .RE
 
@@ -398,8 +409,8 @@
 .na
 \fB\fBpolicy\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これは、デバイスのための追加のセキュリティーポリシーを指定します。特定のドライバが複数の \fBpolicy\fR 属性を持つことができますが、マイナーデバイスの指定が複数の属性に存在することはできません。
 .RE
 
@@ -409,8 +420,8 @@
 .na
 \fB\fBprivs\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 これは、ドライバで使用される特権を指定します。特定のドライバが複数の \fBprivs\fR 属性を持つことができます。
 .RE
 
@@ -420,9 +431,9 @@
 .na
 \fB\fBdevlink\fR\fR
 .ad
-.RS 15n
-.rt  
-これは \fB/etc/devlink.tab\fR 内のエントリを指定します。この値はファイルに書き込まれる行そのものであり、タブは \fB\\t\fR で示されます。詳細は、\fBdevlinks\fR(1M) を参照してください。特定のドライバが複数の \fBdevlink\fR 属性を持つことができます。
+.sp .6
+.RS 4n
+これは \fB/etc/devlink.tab\fR 内のエントリを指定します。この値はファイルに書き込まれる行そのものであり、タブは \fB\et\fR で示されます。詳細は、\fBdevlinks\fR(1M) を参照してください。特定のドライバが複数の \fBdevlink\fR 属性を持つことができます。
 .RE
 
 .SS "依存アクション"
@@ -438,8 +449,8 @@
 .na
 \fB\fBfmri\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 依存パッケージを表す FMRI。これは \fBdependency\fR アクションのキー属性です。\fBfmri\fR 値にパブリッシャーを含めることはできません。パッケージ名は完全であると見なされます。タイプ \fBrequire-any\fR の依存関係は、複数の \fBfmri\fR 属性を持つことができます。\fBfmri\fR 値でバージョンは省略可能ですが、依存関係のタイプによっては、バージョンのない \fBfmri\fR は無意味である場合があります。
 .RE
 
@@ -449,27 +460,108 @@
 .na
 \fB\fBtype\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 依存関係のタイプ。
 .sp
-この値が \fBrequire\fR である場合は、依存関係が必要であり、\fBfmri\fR 属性で指定されたバージョン以上のバージョンを持っている必要があります。バージョンが指定されていない場合は、任意のバージョンが依存関係を満たします。パッケージの必要な依存関係のいずれかを満たすことができない場合、そのパッケージはインストールできません。
+.ne 2
+.mk
+.na
+\fB\fBrequire\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係が必要であり、かつ \fBfmri\fR 属性で指定されたバージョン以上のバージョンを持っている必要があります。バージョンが指定されていない場合は、任意のバージョンが依存関係を満たします。パッケージの必要な依存関係のいずれかを満たすことができない場合、そのパッケージはインストールできません。
+.RE
+
 .sp
-この値が \fBoptional\fR である場合は、依存関係 (存在する場合) が、指定されたバージョンレベル以上に存在する必要があります。
+.ne 2
+.mk
+.na
+\fB\fBoptional\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係が存在する場合は、指定されたバージョンレベル以上である必要があります。
+.RE
+
 .sp
-この値が \fBexclude\fR である場合は、指定されたバージョンレベル以上に依存関係が存在すると、包含するパッケージをインストールできません。バージョンが指定されていない場合、依存パッケージは、依存関係を指定しているパッケージと同時にインストールできません。
+.ne 2
+.mk
+.na
+\fB\fBexclude\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたバージョンレベル以上という依存関係が存在する場合は、含んでいるパッケージをインストールできません。バージョンが指定されていない場合、依存パッケージは、依存関係を指定しているパッケージと同時にインストールできません。
+.RE
+
 .sp
-この値が \fBincorporate\fR である場合、依存関係は省略可能ですが、依存パッケージのバージョンが制約されます。下の「制約と凍結」を参照してください。
+.ne 2
+.mk
+.na
+\fB\fBincorporate\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係はオプションですが、依存するパッケージのバージョンは制約されます。以下の「制約と凍結」を参照してください。
+.RE
+
 .sp
-この値が \fBrequire-any\fR である場合は、複数の \fBfmri\fR 属性で指定された複数の依存パッケージのうちのいずれか 1 つが、依存関係のタイプ \fBrequire\fR と同じ規則に従って依存関係を満たすことができます。
+.ne 2
+.mk
+.na
+\fB\fBrequire-any\fR\fR
+.ad
+.sp .6
+.RS 4n
+複数の \fBfmri\fR 属性で指定された複数の依存パッケージのうちのいずれか 1 つが、依存関係のタイプ \fBrequire\fR と同じ規則に従って依存関係を満たすことができます。
+.RE
+
 .sp
-この値が \fBconditional\fR である場合は、\fBpredicate\fR 属性で定義されたパッケージがシステム上に存在する場合にのみ依存関係が必要です。
+.ne 2
+.mk
+.na
+\fB\fBconditional\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係は、\fBpredicate\fR 属性で定義されたパッケージがシステム上に存在する場合にのみ必要です。
+.RE
+
 .sp
-この値が \fBorigin\fR である場合は、依存関係 (存在する場合) が、インストールの前に変更されるイメージ上の指定された値以上に存在する必要があります。\fBroot-image\fR 属性の値が \fBtrue\fR である場合、このパッケージをインストールするには、/ をルートとするイメージ上に依存関係が存在する必要があります。
+.ne 2
+.mk
+.na
+\fB\fBorigin\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係が存在する場合、依存関係はインストールの前に変更されるイメージ上の指定された値以上である必要があります。\fBroot-image\fR 属性の値が \fBtrue\fR である場合、このパッケージをインストールするには、/ をルートとするイメージ上に依存関係が存在する必要があります。
+.RE
+
 .sp
-この値が \fBgroup\fR である場合は、パッケージがイメージ回避リスト上にないかぎり、依存関係が必要です。廃止されたパッケージは、暗黙のうちにグループの依存関係を満たすことに注意してください。\fBpkg\fR(1) の \fBavoid\fR サブコマンドを参照してください。
+.ne 2
+.mk
+.na
+\fB\fBgroup\fR \fR
+.ad
+.sp .6
+.RS 4n
+依存関係は、パッケージがイメージ回避リスト上にないかぎり必要です。廃止されたパッケージは、暗黙のうちにグループの依存関係を満たすことに注意してください。\fBpkg\fR(1) の \fBavoid\fR サブコマンドを参照してください。
+.RE
+
 .sp
-この値が \fBparent\fR である場合は、このイメージが子イメージでなければ、依存関係は無視されます。このイメージが子イメージである場合は、親イメージ内に依存関係が存在する必要があります。\fBparent\fR 依存関係でのパッケージバージョンの照合は、\fBincorporate\fR 依存関係で使用されるものと同じです。
+.ne 2
+.mk
+.na
+\fB\fBparent\fR\fR
+.ad
+.sp .6
+.RS 4n
+依存関係は、イメージが子イメージでない場合は無視されます。このイメージが子イメージである場合は、親イメージ内に依存関係が存在する必要があります。\fBparent\fR 依存関係でのパッケージバージョンの照合は、\fBincorporate\fR 依存関係で使用されるものと同じです。
+.RE
+
 .RE
 
 .sp
@@ -478,8 +570,8 @@
 .na
 \fB\fBpredicate\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 \fBconditional\fR 依存関係の述語を表す FMRI。
 .RE
 
@@ -489,8 +581,8 @@
 .na
 \fB\fBroot-image\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 先に説明した \fBorigin\fR 依存関係に対してのみ有効です。
 .RE
 
@@ -510,8 +602,8 @@
 .na
 \fB\fBlicense\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 これは \fBlicense\fR アクションのキー属性です。この属性は、ユーザーがライセンスのテキスト自体を読まなくてもその内容を判断できるように支援するための、ライセンスの意味のある説明を提供します。この値のいくつかの例を次に示します。
 .RS +4
 .TP
@@ -561,7 +653,7 @@
 .el o
 Simplified BSD License
 .RE
-上に示すように、可能な場合は常にライセンスのバージョンを説明に含めることをお勧めします。\fBlicense\fR 値は、パッケージ内で一意である必要があります。
+\fBlicense\fR 値は、パッケージ内で一意である必要があります。上のいくつかの例に示すように、説明にライセンスのバージョンを含めることをお勧めします。パッケージに複数のライセンスに基づくコードが含まれる場合、複数の \fBlicense\fR アクションを使用します。ライセンス属性値の長さは、64 文字以下にしてください。
 .RE
 
 .sp
@@ -570,8 +662,8 @@
 .na
 \fB\fBmust-accept\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 \fBtrue\fR の場合は、関連するパッケージをインストールまたは更新するには、ユーザーがこのライセンスに同意する必要があります。この属性を省略すると、\fBfalse\fR と同等になります。同意の方法 (たとえば、対話型または構成ベース) は、クライアントに任されています。
 .RE
 
@@ -581,8 +673,8 @@
 .na
 \fB\fBmust-display\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 \fBtrue\fR の場合は、パッケージ化の操作中に、クライアントがこのアクションのペイロードを表示する必要があります。この値を省略すると、\fBfalse\fR と同等になります。この属性は、コピーライト表示に使用してはいけません。操作中に表示する必要のある実際のライセンスまたはその他の素材にのみ使用してください。表示の方法は、クライアントに任されています。
 .RE
 
@@ -599,8 +691,8 @@
 .na
 \fB\fBcategory\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBCATEGORY\fR パラメータの値。デフォルト値は \fBsystem\fR です。
 .RE
 
@@ -610,8 +702,8 @@
 .na
 \fB\fBdesc\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBDESC\fR パラメータの値。
 .RE
 
@@ -621,8 +713,8 @@
 .na
 \fB\fBhotline\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBHOTLINE\fR パラメータの値。
 .RE
 
@@ -630,10 +722,10 @@
 .ne 2
 .mk
 .na
-\fB\fBname\fR \fR
+\fB\fBname\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBNAME\fR パラメータの値。デフォルト値は \fBnone provided\fR です。
 .RE
 
@@ -643,8 +735,8 @@
 .na
 \fB\fBpkg\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 インストールされるパッケージの略語。デフォルト値は、パッケージの FMRI の名前です。これは \fBlegacy\fR アクションのキー属性です。
 .RE
 
@@ -654,8 +746,8 @@
 .na
 \fB\fBvendor\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBVENDOR\fR パラメータの値。
 .RE
 
@@ -665,8 +757,8 @@
 .na
 \fB\fBversion\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 VERSION パラメータの値。デフォルト値は、パッケージの FMRI のバージョンです。
 .RE
 
@@ -681,7 +773,7 @@
 .ne 2
 .mk
 .na
-\fB\fBname\fR \fR
+\fB\fBname\fR\fR
 .ad
 .RS 9n
 .rt  
@@ -706,10 +798,21 @@
 .ne 2
 .mk
 .na
+\fB\fBpkg.fmri\fR\fR
+.ad
+.sp .6
+.RS 4n
+「説明」セクションの「パッケージの FMRI とバージョン」を参照してください。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBinfo.classification\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 \fBpkg\fR(5) クライアントがパッケージを分類するために使用できる 1 つ以上のトークン。この値には、スキーム (「org.opensolaris.category.2008」や「org.acm.class.1998」など) と実際の分類 (「アプリケーション/ゲーム」など) がコロン (:) で区切られて含まれています。
 .RE
 
@@ -719,8 +822,8 @@
 .na
 \fB\fBpkg.description\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 パッケージの内容と機能の詳細な説明。通常は、1 つの段落程度の長さです。
 .RE
 
@@ -730,8 +833,8 @@
 .na
 \fB\fBpkg.obsolete\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 \fBtrue\fR の場合、パッケージは廃止としてマークされています。廃止されたパッケージには、ほかの設定アクション以外のアクションは存在せず、また名前変更としてマークすることはできません。
 .RE
 
@@ -741,8 +844,8 @@
 .na
 \fB\fBpkg.renamed\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 \fBtrue\fR の場合は、パッケージの名前が変更されました。このパッケージには、このパッケージの名前が変更された先のパッケージバージョンを指す 1 つ以上の \fBdepend\fR アクションも存在する必要があります。パッケージを名前変更と廃止の両方としてマークすることはできませんが、それ以外は任意の数の設定アクションが存在できます。
 .RE
 
@@ -752,8 +855,8 @@
 .na
 \fB\fBpkg.summary\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 パッケージの短い、1 行の説明。
 .RE
 
@@ -767,8 +870,8 @@
 .na
 \fB\fBgroupname\fR\fR
 .ad
-.RS 13n
-.rt  
+.sp .6
+.RS 4n
 グループの名前の値。
 .RE
 
@@ -778,8 +881,8 @@
 .na
 \fB\fBgid\fR\fR
 .ad
-.RS 13n
-.rt  
+.sp .6
+.RS 4n
 グループの一意の数値 ID。デフォルト値は、100 未満の最初に空いているグループです。
 .RE
 
@@ -796,8 +899,8 @@
 .na
 \fB\fBusername\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ユーザーの一意の名前。
 .RE
 
@@ -807,8 +910,8 @@
 .na
 \fB\fBpassword\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ユーザーの暗号化パスワード。デフォルト値は \fB*LK*\fR です。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -818,8 +921,8 @@
 .na
 \fB\fBuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ユーザーの一意の UID。デフォルト値は、100 未満の最初に空いている値です。
 .RE
 
@@ -829,9 +932,9 @@
 .na
 \fB\fBgroup\fR \fR
 .ad
-.RS 15n
-.rt  
-ユーザーの一次グループの名前。\fB/etc/group\fR に存在する必要があります。
+.sp .6
+.RS 4n
+ユーザーのプライマリグループの名前。\fB/etc/group\fR に存在する必要があります。
 .RE
 
 .sp
@@ -840,8 +943,8 @@
 .na
 \fB\fBgcos-field\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 \fB/etc/passwd\fR 内の \fBgcos\fR フィールドの値。デフォルト値は \fBusername\fR です。
 .RE
 
@@ -851,8 +954,8 @@
 .na
 \fB\fBhome-dir\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ユーザーのホームディレクトリ。デフォルト値は / です。
 .RE
 
@@ -862,8 +965,8 @@
 .na
 \fB\fBlogin-shell\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 ユーザーのデフォルトのシェル。デフォルト値は空です。
 .RE
 
@@ -873,9 +976,9 @@
 .na
 \fB\fBgroup-list\fR\fR
 .ad
-.RS 15n
-.rt  
-ユーザーが属している二次グループ。\fBgroup\fR(4) を参照してください。
+.sp .6
+.RS 4n
+ユーザーが属しているセカンダリグループ。\fBgroup\fR(4) を参照してください。
 .RE
 
 .sp
@@ -884,8 +987,8 @@
 .na
 \fB\fBftpuser\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 \fBtrue\fR または \fBfalse\fR に設定できます。\fBtrue\fR のデフォルト値は、ユーザーが FTP 経由のログインを許可されていることを示します。\fBftpusers\fR(4) を参照してください。
 .RE
 
@@ -895,8 +998,8 @@
 .na
 \fB\fBlastchg\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 1970 年 1 月 1 日と、パスワードが最後に変更された日付の間の日数。デフォルト値は空です。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -904,10 +1007,10 @@
 .ne 2
 .mk
 .na
-\fB\fBmin\fR\fR
+\fB\fBmin\fR \fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 パスワード変更の間の必要な最小日数。パスワードの有効期限を有効にするには、このフィールドを 0 以上に設定する必要があります。デフォルト値は空です。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -915,10 +1018,10 @@
 .ne 2
 .mk
 .na
-\fB\fBmax\fR\fR
+\fB\fBmax\fR \fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 パスワードが有効な最大日数。デフォルト値は空です。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -928,8 +1031,8 @@
 .na
 \fB\fBwarn\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 パスワードの期限が切れる前にユーザーに警告が表示される日数。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -939,8 +1042,8 @@
 .na
 \fB\fBinactive\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 そのユーザーに許可されている非活動の日数。これはマシンごとにカウントされます。最終ログインに関する情報は、そのマシンの \fBlastlog\fR ファイルから取得されます。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -950,8 +1053,8 @@
 .na
 \fB\fBexpire\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 UNIX エポック (1970 年 1 月 1 日) 以降の日数として表される絶対的な日付。この日数に達すると、ログインを使用できなくなります。たとえば、13514 の期限切れの値は、ログインの有効期限が 2007 年 1 月 1 日であることを指定します。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -961,8 +1064,8 @@
 .na
 \fB\fBflag\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 空に設定されています。\fBshadow\fR(4) を参照してください。
 .RE
 
@@ -984,7 +1087,7 @@
 .ad
 .sp .6
 .RS 4n
-\fBtrue\fR または \fBfalse\fR に設定できます。パッケージのインストール中に、このアクチュエータが \fBtrue\fR に設定されたアクションがインストールまたは更新された場合は、パッケージ化のトランザクションをリブートが必要であるとして通知できます。特定のクライアント実装では、イメージがライブシステムイメージである場合、イメージの複製を使用してパッケージ操作全体を実行するなどの、追加の手順が実行される可能性があります。
+\fBtrue\fR または \fBfalse\fR に設定できます。このアクチュエータは、パッケージシステムがライブイメージ上で動作している場合、タグ付きアクションの更新または削除を新しいブート環境で実行する必要があることを宣言します。新しいブート環境の作成は、\fBbe-policy\fR イメージプロパティーによって制御されます。\fBbe-policy\fR プロパティーについての詳細は、\fBpkg\fR(1) のマニュアルページの「イメージプロパティー」セクションを参照してください。
 .RE
 
 .sp
@@ -995,11 +1098,29 @@
 .ad
 .sp .6
 .RS 4n
-これらの各アクチュエータは、パッケージのインストールまたは削除中に操作するサービスインスタンスの FMRI の値を取ります。\fBdisable_fmri\fR を指定すると、\fBsvcadm\fR(1M) の \fBdisable\fR サブコマンドに従って、アクションの削除の前に特定の FMRI が無効になります。\fBrefresh_fmri\fR および \fBrestart_fmri\fR を指定すると、\fBsvcadm\fR(1M) の対応するサブコマンドに従って、アクションのインストールまたは更新のあとに特定の FMRI が更新または再起動されます。最後に、\fBsuspend_fmri\fR を指定すると、アクションのインストールフェーズの前に特定の FMRI が一時的に無効になり、そのフェーズが完了したあとに有効になります。
+これらの各アクチュエータは、パッケージのインストールまたは削除中に操作するサービスインスタンスの FMRI の値を取ります。\fBdisable_fmri\fR を指定すると、\fBsvcadm\fR(1M) の \fBdisable\fR サブコマンドに従って、アクションの削除の前に特定の FMRI が無効になります。\fBrefresh_fmri\fR および \fBrestart_fmri\fR を指定すると、\fBsvcadm\fR(1M) の対応するサブコマンドに従って、アクションのインストール、更新、または削除のあとに特定の FMRI が更新または再起動されます。最後に、\fBsuspend_fmri\fR を指定すると、アクションのインストールフェーズの前に特定の FMRI が一時的に無効になり、そのフェーズが完了したあとに有効になります。
 .sp
 この値には、複数のサービスインスタンスに一致するパターンを含めることができます。ただし、それをインスタンスを示さずに暗黙的に行うのではなく、\fBsvcs\fR(1) によって受け入れられた glob を使用して明示的に行う必要があります。
 .RE
 
+.SH メディエーション
+.sp
+.LP
+メディエータは、一連の関連するシンボリックリンクまたはハードリンクを表す名前です。2 つ以上のリンクアクションが同じパスとメディエータ名を持つ場合、ユーザーまたはパッケージシステムは、バージョン、実装、または優先順位に基づいてリンクターゲットを選択します。メディエータ属性については、「リンクアクション」を参照してください。
+.sp
+.LP
+次の例は、リンクがバージョンによって選択される、\fBjava\fR という名前のメディエータの 2 つの異なるインスタンスを示しています。これらの 2 つの \fBlink\fR アクションは 2 つの異なるパッケージに出現します。
+.sp
+.in +2
+.nf
+link mediator=java mediator-version=1.6 path=usr/java target=jdk/jdk1.6.0_31
+link mediator=java mediator-version=1.7 path=usr/java target=jdk/jdk1.7.0_02
+.fi
+.in -2
+
+.sp
+.LP
+このリンクパスのバージョンを選択する方法については、\fBpkg\fR(1) のマニュアルページの \fBset-mediator\fR サブコマンドを参照してください。バージョンを選択するには、両方のパッケージがインストールされている必要があります。
 .SH 制約と凍結
 .sp
 .LP
@@ -1012,7 +1133,7 @@
 オペレーティングシステムのほとんどの部分は、\fBincorporation\fR と呼ばれるパッケージによってカプセル化されています。これらのパッケージは主に、\fBincorporate\fR 依存関係によって表される制約を提供します。
 .sp
 .LP
-上で説明したように、組み込まれたパッケージがシステム上に存在する必要はありませんが、存在する場合は、包括的な最小バージョンと排他的な最大バージョンの両方を指定します。たとえば、依存する FMRI のバージョンが 1.4.3 の場合は、1.4.3 未満のバージョンも、1.4.4 以上のどのバージョンも依存関係を満たしません。ただし、1.4.3.7 などの、ドットで区切られた並びを拡張しただけのバージョンは許可されます。
+上で説明したように、組み込まれたパッケージがシステム上に存在する必要はありませんが、存在する場合は、包括的な最小バージョンと排他的な最大バージョンの両方を指定します。たとえば、依存する FMRI のバージョンが 1.4.3 の場合、1.4.3 未満のバージョンは依存関係を満たさず、1.4.4 以上のバージョンでも依存関係を満たしません。ただし、1.4.3.7 など、単にドット形式の数列を拡張したバージョンは許可されます。
 .sp
 .LP
 incorporation は、システムの各部の同期的なアップグレードを強制的に行うために使用されます。C ライブラリやカーネルなどの一部のコンポーネントでは、これは基本的な要件です。ほかには依存関係が存在しない単純なユーザーランドコンポーネントなどのその他のコンポーネントでは、incorporation の特定のバージョンから参照できるテストされた、既知の一連のパッケージバージョンを提供するためだけに、同期アップグレードが使用されます。
@@ -1028,7 +1149,7 @@
 .sp
 .LP
 凍結がパッケージシステムによって自動的に解除されることはありません。制約を緩和するには、\fBpkg unfreeze\fR コマンドを使用します。
-.SH パブリッシャーとリポジトリ
+.SH 発行元とリポジトリ
 .sp
 .LP
 上で詳細に説明したように、パブリッシャーとは単に、パッケージクライアントがパッケージのプロバイダを識別するために使用する名前です。パブリッシャーは、パッケージリポジトリまたはパッケージアーカイブ、あるいはその両方を使用してパッケージを配布できます。現在パッケージシステムでサポートされているリポジトリのタイプには、起点リポジトリとミラーリポジトリの 2 つがあります。
@@ -1038,40 +1159,130 @@
 .sp
 .LP
 \fBミラー\fRは、パッケージの内容 (ファイル) のみを含むパッケージリポジトリです。イメージ内の特定のパブリッシャーに対して 1 つ以上のミラーが構成されている場合、クライアント API はパッケージ内容の取得のためのミラーを優先し、パッケージの内容の取得元として最適なミラーを選択しようとします。ミラーが到達不可能か、必要な内容が含まれていないか、またはより低速な場合、クライアント API は、構成されているいずれかの起点リポジトリから内容を取得します。ミラーは、\fBpkg.depotd\fR(1M) の動的ミラー機能を使用している、信頼できる一連のクライアント間の内容共有に使用されることを目的にしています。ミラーはまた、パッケージのメタデータへのアクセスを認証するために使用されることも目的にしています。ただし、パッケージの内容は認証なしで配布します。たとえば、あるクライアントが、アクセスするには SSL キーと証明書のペアが必要な \fBhttps\fR 起点と、パッケージの内容を提供する \fBhttp\fR ミラーを使用して構成される可能性があります。このようにして、認可クライアントだけがパッケージをインストールまたは更新できるようにしながら、パッケージ内容の取得のための認証のオーバーヘッドが回避されます。ミラーは、\fBfile\fR という名前のサブディレクトリとその親を除く、リポジトリのすべてのサブディレクトリを削除することによって作成できます。また、\fBpkg.depotd\fR(1M) のミラーモードを使用すると、起点リポジトリもミラーとしてプロビジョニングできます。
-.SH プロパティー
+.SH 大域ゾーンと非大域ゾーンの更新
+.sp
+.LP
+\fBpkg\fR システムは、非大域ゾーンを強制的に大域ゾーンと同期された状態に保持します。つまり、同じカーネルが確実に実行されるようにするために、特定のパッケージを大域ゾーンとすべての非大域ゾーンで同じバージョンにする必要があります。このために、\fBpkg\fR は \fBparent\fR 依存関係を使用して、非大域ゾーンに特定の制約を課します。\fBparent\fR 依存関係についての詳細は、上の「依存アクション」を参照してください。
+.sp
+.LP
+大域ゾーンが非大域ゾーンに課す制限のため、非大域ゾーンは大域ゾーンのパッケージにアクセスできる必要があり、かつ同様の発行元構成にする必要があります。これらの目的はどちらも、\fBシステムリポジトリ\fR を使用して実現されます (\fBpkg.sysrepo\fR(1M) のマニュアルページを参照)。システムリポジトリは、大域ゾーン内で構成された発行元へのアクセスと、これらの発行元が構成されている方法に関する情報を提供します。インストールまたは更新中に非大域ゾーンで別のパッケージが選択されないようにするために、発行元の検索順序で、システム発行元には非大域ゾーン内で構成された発行元より高くランク付けされます。発行元の検索順序については、\fBpkg\fR(1) のマニュアルページの \fBpkg set-publisher\fR コマンドを参照してください。
+.sp
+.LP
+システム上のすべての非大域ゾーンを更新するには、大域ゾーン内で \fBpkg update\fR コマンドを引数なしで使用します。このコマンドは大域ゾーンに対して、また各非大域ゾーンに対して再帰的に動作します。非大域ゾーンを大域ゾーン内で行われた変更と同期された状態にするために、非大域ゾーンに対して必要な最小の変更が加えられます。たとえば、パッケージ \fBfoo\fR が大域ゾーンと非大域ゾーンの両方にバージョン 1 でインストールされており、システムリポジトリ内でバージョン 2 が使用可能であると想定します。\fBfoo\fR に親の依存関係が存在する場合、\fBparent\fR 依存関係によってパッケージは強制的に同期された状態に保持されるため、\fBpkg update foo\fR は \fBfoo\fR を大域ゾーンと非大域ゾーンの両方でバージョン 2 に更新します。\fBfoo\fR に親の依存関係が存在しない場合、\fBfoo\fR は大域ゾーンでバージョン 2 に更新されますが、非大域ゾーンではバージョン 1 のままになります。
+.SH ファセットとバリアント
+.sp
+.LP
+ソフトウェアには、省略可能なコンポーネントや、相互に排他的なコンポーネントが含まれることがあります。省略可能なコンポーネントの例には、ロケールやドキュメントがあります。相互に排他的なコンポーネントの例には、SPARC バイナリと x86 バイナリや、デバッグバイナリと非デバッグバイナリなどがあります。
+.sp
+.LP
+IPS では、省略可能なコンポーネントを\fBファセット\fR、相互に排他的なコンポーネントを\fBバリアント\fRと呼びます。ファセットとバリアントはパッケージアクションのタグとして指定します。各ファセットタグおよびバリアントタグには名前と値があります。1 つのアクションに複数のファセットタグおよびバリアントタグを付けることができます。複数のファセットおよびバリアントタグのあるコンポーネントの例には、開発者によって使われるアーキテクチャー固有のヘッダーファイルや SPARC 大域ゾーン専用のコンポーネントなどがあります。
+.sp
+.LP
+バリアントタグの例は \fBvariant.arch=sparc\fR です。ファセットタグの例は \fBfacet.devel=true\fR です。ファセットとバリアントは、\fBfacet.\fR や \fB variant.\fR を先頭に付けずに参照されることがよくあります。
+.sp
+.LP
+ファセットとバリアントはイメージの特殊なプロパティーであり、個々のパッケージには設定できません。イメージに設定されたファセットおよびバリアントの現在の値を表示するには、\fBpkg\fR(1) のマニュアルページに示すように、\fBpkg facet\fR コマンドと \fBpkg variant\fR コマンドを使用します。イメージに設定されたファセットおよびバリアントの値を変更するには、\fBpkg change-facet\fR コマンドと \fB pkg change-variant\fR コマンドを使用します。
+.sp
+.LP
+ファセットはブール型です。それらには \fBtrue\fR (有効) または \fBfalse\fR (無効) のみ設定できます。デフォルトで、イメージ内のすべてのファセットは、\fBtrue\fR に設定されていると見なされます。アクションのファセットタグの値には \fBtrue\fR のみを指定すべきであり、それ以外の値では動作が不確定になります。イメージに設定されるファセットは、\fBdoc.man\fR などの完全なファセットか、\fBlocale.*\fR などのパターンになります。これは、ファセット名前空間の一部を無効にし、その中の個々のファセットのみを有効にする場合に役立ちます。たとえば、次の例に示すように、すべてのロケールを無効にしてから、1 つか 2 つの特定のロケールのみを有効にすることができます。
+.sp
+.in +2
+.nf
+# \fBpkg change-facet locale.*=false\fR
+[output about packages being updated]
+# \fBpkg change-facet locale.en_US=true\fR
+[output about packages being updated]
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+ほとんどのバリアントは任意の数の値を設定できます。たとえば、\fBarch\fR バリアントには、\fBi386\fR、\fBsparc\fR、\fBppc\fR、\fBarm\fR、またはディストリビューションがサポートしているどのようなアーキテクチャーでも設定できます。(Oracle Solaris では \fBi386\fR と \fBsparc\fR のみが使用されます。)例外は \fBdebug\fR バリアントです。\fBdebug\fR バリアントは、\fBtrue\fR または \fBfalse\fR のみ設定でき、ほかの値では動作が不定になります。ファイルアクションに非デバッグバージョンとデバッグバージョンの両方がある場合、次の例に示すように、両方のバージョンに該当する \fBdebug\fR バリアントが明示的に設定されている必要があります。
+.sp
+.in +2
+.nf
+file group=sys mode=0644 overlay=allow owner=root \e
+  path=etc/motd pkg.csize=115 pkg.size=103 preserve=true \e
+  variant.debug.osnet=true
+
+file group=sys mode=0644 overlay=allow owner=root \e
+  path=etc/motd pkg.csize=68 pkg.size=48 preserve=true \e
+  variant.debug.osnet=false 
+.fi
+.in -2
+
+.sp
+.LP
+バリアントを使用するパッケージをインストールするために、バリアント値をイメージに設定する必要があります。\fBarch\fR および \fBzone\fR バリアントは、イメージを作成し、その初期コンテンツをインストールするプログラムによって設定されます。イメージ内の \fBdebug.*\fR バリアントはデフォルトで \fBfalse\fR です。
 .sp
 .LP
-イメージには、1 つ以上のプロパティーを関連付けることができます。これらのプロパティーは、イメージの目的、内容、および動作に関する情報を格納するために使用できます。完全なリストについては、\fBpkg\fR(1) を参照してください。
+イメージに設定されたファセットとバリアントは、特定のアクションがインストールされるかどうかに影響します。
+.RS +4
+.TP
+.ie t \(bu
+.el o
+ファセットまたはバリアントタグのないアクションは常にインストールされます。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+ファセットタグのあるアクションは、イメージ上のタグに一致するすべてのファセットまたはファセットパターンが \fBfalse\fR に設定されていないかぎり、インストールされます。いずれかのファセットが \fBtrue\fR に設定されているか、明示的に設定されていない (\fBtrue\fR はデフォルト) 場合、アクションがインストールされます。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+バリアントタグのあるアクションは、すべてのバリアントタグの値がイメージに設定されている値と同じ場合にのみインストールされます。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+ファセットタグとバリアントタグの両方があるアクションは、ファセットとバリアントの両方でアクションのインストールが許可されている場合にインストールされます。
+.RE
+.sp
+.LP
+独自のファセットおよびバリアントタグを作成できます。Oracle Solaris では、次のタグが一般に使用されます。
+.sp
+
+.sp
+.TS
+tab();
+cw(2.75i) cw(2.75i) 
+lw(2.75i) lw(2.75i) 
+.
+バリアント名取り得る値
+_
+\fBvariant.arch\fR\fBsparc\fR、\fBi386\fR
+\fBvariant.opensolaris.zone\fR\fBglobal\fR、\fBnonglobal\fR
+\fBvariant.debug.*\fR\fBtrue\fR、\fBfalse\fR
+.TE
+
+.sp
+.LP
+次のリストに、Oracle Solaris で使用される小さなファセットタグの例を示します。
+.sp
+.in +2
+.nf
+facet.devel             facet.doc
+facet.doc.html          facet.doc.info
+facet.doc.man           facet.doc.pdf
+facet.locale.de         facet.locale.en_GB
+facet.locale.en_US      facet.locale.fr
+facet.locale.ja_JP      facet.locale.zh_CN
+.fi
+.in -2
+
 .SH イメージポリシー
 .sp
 .LP
-ポリシーは、ブール値を使用してイメージプロパティーで定義されます。サポートされるポリシーには次のものがあります。
-.sp
-.ne 2
-.mk
-.na
-\fB\fBflush-content-cache-on-success\fR\fR
-.ad
-.sp .6
-.RS 4n
-true の場合は、パッケージのインストールが成功したあと、ダウンロードされたファイルのキャッシュが消去されます。デフォルト値: \fBTrue\fR.
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fBsend-uuid\fR\fR
-.ad
-.sp .6
-.RS 4n
-true の場合は、パブリッシャーへのイメージを識別する一意の識別子 (UUID) が、すべての要求に対して送信されます。デフォルト値: \fBTrue\fR。
-.RE
-
+イメージポリシーはブール値を持つイメージプロパティーによって定義されます。\fBflush-content-cache-on-success\fR および \fBsend-uuid\fR プロパティーについてとそれらの値の表示および変更方法については、\fBpkg\fR(1) のマニュアルページのイメージプロパティーに関する項目を参照してください。
 .SH ファイル
 .sp
 .LP
-\fBpkg\fR(5) イメージは大きなファイルシステム内の任意の場所に配置できるため、相対パスを区別するためにトークン \fB$IMAGE_ROOT\fR が使用されます。標準的なシステムインストールでは、\fB$IMAGE_ROOT\fR は / と同等です。
+\fBpkg\fR(5) イメージはより大きなファイルシステム内に任意に配置できるため、トークン \fB$IMAGE_ROOT\fR を使用して相対パスが区別されます。標準的なシステムインストールでは、\fB$IMAGE_ROOT\fR は / と同等です。
 .sp
 .ne 2
 .mk
@@ -1080,7 +1291,7 @@
 .ad
 .sp .6
 .RS 4n
-フルイメージまたは部分イメージのメタデータディレクトリ。
+完全または部分的なイメージのメタデータディレクトリ。
 .RE
 
 .sp
@@ -1096,15 +1307,15 @@
 
 .sp
 .LP
-特定のイメージのメタデータ内の特定のファイルおよびディレクトリに、修復や復旧中に役立つ情報を含めることができます。トークン \fB$IMAGE_META\fR は、そのメタデータを含む最上位レベルのディレクトリを参照するために使用されます。\fB$IMAGE_META\fR は通常、上に示した 2 つのパスのいずれかです。
+特定のイメージのメタデータ内の特定のファイルおよびディレクトリに、修復や復旧中に役立つ情報を含めることができます。トークン \fB$IMAGE_META \fR は、メタデータが含まれる最上位ディレクトリを参照するために使用されます。通常、\fB $IMAGE_META\fR は前述の 2 つのパスのいずれかです。
 .sp
 .ne 2
 .mk
 .na
 \fB\fB$IMAGE_META/lost+found\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 パッケージ操作中に移動された、競合するディレクトリおよびファイルの場所。
 .RE
 
@@ -1114,8 +1325,8 @@
 .na
 \fB\fB$IMAGE_META/publisher\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 パブリッシャーごとに 1 つのディレクトリが含まれます。各ディレクトリにはパブリッシャー固有のメタデータが格納されます。
 .RE
 
@@ -1144,7 +1355,16 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkg\fR(1), \fBpkgsend\fR(1), \fBpkg.depotd \fR(1M), \fBsvcadm\fR(1M), \fBpkginfo\fR(4)
+\fBpkg \fR(1)、\fBpkg\fR(1)、\fBpkg\fR(1M)、\fBpkg\fR(1M)、\fBsvcs\fR(1)、\fBsvcadm\fR(1M)
+.sp
+.LP
+\fI『Adding and Updating Oracle Solaris 11.1 Software Packages』\fR
+.sp
+.LP
+\fI『Copying and Creating Oracle Solaris 11.1 Package Repositories』\fR
+.sp
+.LP
+\fI『Packaging and Delivering Software With the Oracle Solaris 11 Image Packaging System』\fR
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pkgdepend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgdepend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgdepend 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgdepend 1 "2012 年 6 月 22 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgdepend \- Image Packaging System 依存関係アナライザ
 .SH 形式
@@ -12,19 +12,19 @@
 .LP
 .nf
 /usr/bin/pkgdepend generate [-IMm] -d \fIdir\fR [-d \fIdir\fR]
-    [-D \fIname\fR=\fIvalue\fR] [-k \fIpath\fR] \fImanifest_path\fR
+    [-D \fIname\fR=\fIvalue\fR] [-k \fIpath\fR] \fImanifest_file\fR
 .fi
 
 .LP
 .nf
 /usr/bin/pkgdepend resolve [-moSv] [-d \fIoutput_dir\fR]
-    [-s \fIsuffix\fR] \fImanifest_path\fR ...
+    [-s \fIsuffix\fR] \fImanifest_file\fR ...
 .fi
 
 .SH 機能説明
 .sp
 .LP
-\fBpkgdepend\fR は、パッケージの依存関係を生成および解決するために使用されます。パッケージは、ほかのパッケージのファイルに依存することがあります。\fBpkgdepend\fR は通常、ファイル依存関係の生成と、ファイルからパッケージへの解決という 2 つのパスで使用されます。
+\fBpkgdepend\fR コマンドは、パッケージの依存関係を生成および解決します。パッケージは、ほかのパッケージのファイルに依存することがあります。\fBpkgdepend\fR コマンドは通常、ファイル依存関係の生成と、ファイルからパッケージへの解決という 2 つのパスで使用されます。
 .sp
 .LP
 \fBgenerate\fR サブコマンドはパッケージの内容を検査し、そのパッケージにどのような外部ファイルが必要かを判定します。
@@ -42,7 +42,7 @@
 .ad
 .RS 22n
 .rt  
-提供されたファイル内の ELF ヘッダーが依存関係情報のために分析され、\fB-k\fR および \fB-D\fR オプションが指定されていると取得された情報が変更されます。ELF 依存関係についての詳細は、\fBldd\fR(1) および\fI『『リンカーとライブラリ』』\fRを参照してください。
+提供されたファイル内の ELF ヘッダーが依存関係情報のために分析され、\fB-k\fR および \fB-D\fR オプションが指定されていると取得された情報が変更されます。ELF 依存関係についての詳細は、\fBldd\fR および\fI『Linker and Libraries Guide』\fRを参照してください。
 .RE
 
 .sp
@@ -92,64 +92,123 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-R\fR \fIdir\fR\fR
 .ad
-.RS 16n
-.rt  
-\fIdir\fR をルートとするイメージを操作します。ディレクトリが指定されなかったか、または環境に基づいて決定される場合、デフォルトは / です。詳細は、「環境変数」の節を参照してください。
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fIdir\fR をルートとするイメージを操作します。ディレクトリが指定されなかったか、または環境に基づいて決定される場合、デフォルトは / です。詳細は、「環境変数」のセクションを参照してください。
+.RE
+
+.SH サブコマンド
+.sp
+.LP
+サポートされているサブコマンドは次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgdepend generate\fR [\fB-IMm\fR] \fB- d\fR \fIdir\fR [\fB-d\fR \fIdir\fR] [\fB-D\fR \fIname\fR=\fIvalue\fR] [\fB-k\fR \fIpath\fR] \fImanifest_file\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fImanifest_file\fR で指定されたマニフェストのファイルへの依存関係を生成します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fImanifest_file\fR 内で満たされている依存関係を表示します。\fB-I\fR と \fBpkgdepend resolve\fR の結果を使用しないでください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR or \fB-?\fR\fR
+\fB\fB-M\fR\fR
 .ad
-.RS 16n
-.rt  
-使用方法に関するメッセージを表示します。
+.sp .6
+.RS 4n
+分析できなかったファイルタイプのリストを表示します。
 .RE
 
-.SH サブコマンド
 .sp
-.LP
-次のサブコマンドがサポートされています。
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
+.ad
+.sp .6
+.RS 4n
+元のマニフェストを繰り返してから、検出された依存関係をすべて追加します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
-\fB\fBgenerate [\fB-IMm\fR] \fB-d\fR \fI dir\fR [\fB-d\fR \fIdir\fR] [\fB-D\fR \fI name\fR=\fIvalue\fR] [\fB-k\fR \fI path\fR] \fImanifest_path\fR\fR\fR
+\fB\fB-d\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
+マニフェストのファイルを検索するディレクトリのリストに \fIdir\fR を追加します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-D\fR \fIname\fR=\fI value\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fImanifest_path\fR で指定されたマニフェストのファイルへの依存関係を生成します。
-.sp
-\fB-I\fR が指定されている場合は、指定されたマニフェスト内で満たされている依存関係を表示します。
-.sp
-\fB-M\fR が指定されている場合は、分析できなかったファイルタイプのリストを表示します。
-.sp
-\fB-m\fR が指定されている場合は、元のマニフェストを繰り返してから、検出された依存関係をすべて追加します。
+ELF ファイル依存関係のための実行パス内のトークン \fIname\fR を展開する方法として \fIvalue\fR を追加します。
+.RE
+
 .sp
-\fB-d\fR が指定されている場合は、マニフェストのファイルを検索するディレクトリのリストに \fIdir\fR を追加します。
-.sp
-\fB-D\fR が指定されるたびに、ELF ファイル依存関係のための実行パス内のトークン \fIname\fR を展開する方法として \fIvalue\fR を追加します。
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIpath\fR\fR
+.ad
+.sp .6
+.RS 4n
+カーネルモジュールを検索する実行パスのリストに \fIpath\fR を追加します。\fB-k\fR オプションを使用すると、デフォルトのパス (\fB/kernel\fR と \fB/usr/kernel\fR) が削除されます。
 .sp
-\fB-k\fR が指定されるたびに、カーネルモジュールを検索する実行パスのリストに \fIpath\fR を追加します。\fB-k\fR 引数を使用すると、デフォルトのパス (\fB/kernel\fR と \fB/usr/kernel\fR) が削除されます。
-.sp
-\fB-k\fR オプションで指定されるような実行パスは、アクションまたはマニフェスト属性 \fBpkg.depend.runpath\fR を使用して、アクションごとまたはマニフェストごとにも指定できます。\fBpkg.depend.runpath\fR 属性の値は、使用するパスのコロンで区切られた文字列です。
-.sp
-\fB-k\fR の使用は、マニフェストまたはアクションで設定された任意の \fBpkg.depend.runpath\fR 属性によって上書きされます。
+\fB-k\fR オプションで指定されるような実行パスは、アクションまたはマニフェスト属性 \fBpkg.depend.runpath\fR を使用して、アクションごとまたはマニフェストごとにも指定できます。\fBpkg.depend.runpath\fR 属性の値は、使用するパスのコロンで区切られた文字列です。マニフェストまたはアクション内にいずれかの \fBpkg.depend.runpath\fR 属性を設定すると、\fB-k\fR オプションで指定されたパスがオーバーライドされます。
 .sp
 \fBpkg.depend.runpath\fR 属性値の 1 つのコンポーネントとして、特殊なトークン \fB$PKGDEPEND_RUNPATH\fR を使用すると、分析対象のファイルのための標準のシステム実行パスを含めることができます。
-.sp
+.RE
+
 場合によっては、依存関係が自動的に生成されることを回避したいことがあります。たとえば、あるパッケージによって、一連のモジュールをインポートするサンプルの Python スクリプトが提供される場合、そのサンプルスクリプトによってインポートされるこれらのモジュールは、サンプルスクリプトを提供しているパッケージの依存関係ではありません。指定されたファイルに対する依存関係の生成を回避するには、アクションまたはマニフェスト属性 \fBpkg.depend.bypass-generate\fR を使用します。
 .sp
-\fBpkg.depend.bypass-generate\fR 値は、ファイル名に一致する \fBperl5\fR の正規表現です。これらの正規表現は、ファイルパスの先頭と最後に暗黙的に固定されます。次の例で指定された値は \fBthis/that\fR に一致しますが、\fBsomething/this/that/the/other\fR には一致しません。
+\fBpkg.depend.bypass-generate\fR 値は、ファイル名に一致する Python の正規表現です。これらの正規表現は、ファイルパスの先頭と最後に暗黙的に固定されます。次の例で指定されている値は \fBthis/that\fR に一致しますが、\fBsomething/this/that/the/other\fR には一致しません。
 .sp
 .in +2
 .nf
@@ -157,29 +216,86 @@
 .fi
 .in -2
 
+Python 正規表現の構文については、コマンド \fBpydoc re\fR を使用するか、または \fBhttp://docs.python.org/dev/howto/regex.html\fR にあるより完全なドキュメントを参照してください。
+.sp
+\fBpkgdepend generate\fR 入力マニフェストに SMF マニフェストファイルが含まれる場合、それらの SMF マニフェストファイルによって宣言されている SMF サービスまたはインスタンスが \fBpkgdepend\fR の出力に含まれます。これらの SMF サービスまたはインスタンスは、\fBorg.opensolaris.smf.fmri\fR の名前で \fBset\fR アクションの形式で含まれます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgdepend resolve\fR [\fB-moSv\fR] [\fB-d\fR \fIoutput_dir\fR] [\fB-s\fR \fI suffix\fR] \fImanifest_file\fR ...\fR
+.ad
+.sp .6
+.RS 4n
+ファイルへの依存関係を、これらのファイルを提供するパッケージへの依存関係に変換します。依存関係は、まずコマンド行に指定されたマニフェストに基づいて解決され、次にシステムにインストールされているパッケージに基づいて解決されます。デフォルトでは、各マニフェストの依存関係は \fB\fImanifest_file\fR.res\fR という名前のファイルに格納されます。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
+.ad
+.sp .6
+.RS 4n
+解決された依存関係を追加する前に、\fBgenerate\fR ステップによって生成された依存関係をすべて削除して、マニフェストを繰り返します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR\fR
+.ad
+.sp .6
+.RS 4n
+結果を標準出力に書き込みます。このオプションは、人による使用を目的にしています。この出力をファイルに追加すると、無効なマニフェストが生成されることがあります。マニフェスト処理のパイプラインでは、\fB-o\fR の代わりに \fB-d\fR または \fB-s\fR オプションを使用することを強くお勧めします。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBresolve [\fB-moSv\fR] [\fB-d\fR \fI output_dir\fR] [\fB-s\fR \fIsuffix\fR] \fI manifest_path\fR ...\fR\fR
+\fB\fB-d\fR \fIoutput_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された各マニフェストの解決された依存関係を \fIoutput_dir\fR 内の個別のファイルに書き込みます。デフォルトでは、各ファイルには、そのファイルに書き込まれた依存関係のソースだったマニフェストと同じベース名が付けられます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIsuffix\fR\fR
 .ad
 .sp .6
 .RS 4n
-ファイルへの依存関係を、これらのファイルを提供するパッケージへの依存関係に変換します。依存関係は、まずコマンド行で指定されたマニフェストに対して解決され、次にシステムにインストールされているパッケージに対して解決されます。デフォルトでは、各マニフェストの依存関係は \fB\fImanifest_path\fR.res\fR という名前のファイルに格納されます。
-.sp
-\fB-m\fR が指定されている場合は、解決された依存関係を追加する前に、\fBgenerate\fR ステップによって生成された依存関係をすべて削除して、マニフェストを繰り返します。
-.sp
-\fB-o\fR が指定されている場合は、結果を標準出力に書き込みます。このオプションは、人による使用を目的にしています。この出力をファイルに追加すると、無効なマニフェストが生成されることがあります。マニフェスト処理のパイプラインでは、\fB-o\fR の代わりに \fB-d\fR または \fB-s\fR オプションを使用することを強くお勧めします。
+出力ファイルごとに、解決された依存関係のソースだったファイルのベース名に \fIsuffix\fR を追加します。\fIsuffix\fR が \fI\&.suffix\fR でない場合、ピリオド (.) が \fIsuffix\fR の前に付加されます。
+.RE
+
 .sp
-\fB-d\fR が指定されている場合は、指定された各マニフェストの解決された依存関係を \fIoutput_dir\fR 内の個別のファイルに書き込みます。デフォルトでは、各ファイルには、そのファイルに書き込まれた依存関係のソースだったマニフェストと同じベース名が付けられます。
-.sp
-\fB-s\fR が指定されている場合は、出力ファイルごとに、解決された依存関係のソースだったファイルのベース名に \fIsuffix\fR を追加します。「.」が \fIsuffix\fR に付加されます (指定されていない場合)。
+.ne 2
+.mk
+.na
+\fB\fB-S\fR\fR
+.ad
+.sp .6
+.RS 4n
+コマンド行で指定されたマニフェストに対してのみ解決し、システムにインストールされているマニフェストに対しては解決しません。
+.RE
+
 .sp
-\fB-S\fR が指定されている場合は、コマンド行で指定されたマニフェストに対してのみ解決し、システムにインストールされているマニフェストに対しては解決しません。
-.sp
-\fB-v\fR が指定されている場合は、追加のパッケージ依存関係デバッグ用のメタデータを含めます。
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+追加のパッケージ依存関係デバッグ用のメタデータを含めます。
+.RE
+
 .RE
 
 .SH 使用例
@@ -284,10 +400,10 @@
 # Add runpath and bypass-generate attributes:
 #
 file NOHASH path=opt/python/foo/file.py mode=0644 group=sys owner=root \e
-    pkg.depend.bypass-generate=^.*/test.py.*$ \e
-    pkg.depend.bypass-generate=^.*/testmodule.so$ \e
-    pkg.depend.bypass-generate=^.*/test.so$ \e
-    pkg.depend.bypass-generate=^usr/lib/python2.6/vendor-packages/xdg/.*$ \e
+    pkg.depend.bypass-generate=.*/test.py.* \e
+    pkg.depend.bypass-generate=.*/testmodule.so \e
+    pkg.depend.bypass-generate=.*/test.so \e
+    pkg.depend.bypass-generate=usr/lib/python2.6/vendor-packages/xdg/.* \e
     pkg.depend.runpath=$PKGDEPEND_RUNPATH:/opt/python
 
 $ \fBpkgdepend generate -d proto manifest.py\fR
@@ -310,7 +426,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -330,7 +446,7 @@
 .ad
 .RS 6n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
@@ -341,7 +457,7 @@
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
--- a/src/man/ja_JP/pkgdiff.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgdiff.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgdiff 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgdiff 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgdiff \- パッケージマニフェストの比較
 .SH 形式
@@ -23,8 +23,8 @@
 .na
 \fB+ \fIcomplete_action\fR\fR
 .ad
-.RS 21n
-.rt  
+.sp .6
+.RS 4n
 このアクションは \fIfile2\fR に含まれていますが、\fIfile1\fR には含まれていません。
 .RE
 
@@ -34,8 +34,8 @@
 .na
 \fB- \fIcomplete_action\fR\fR
 .ad
-.RS 21n
-.rt  
+.sp .6
+.RS 4n
 このアクションは \fIfile1\fR に含まれていますが、\fIfile2\fR には含まれていません。
 .RE
 
@@ -52,8 +52,8 @@
 .na
 \fB- \fIattribute1\fR=\fIvalue1\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 この \fIattribute\fR,\fIvalue\fR は \fIfile1\fR に含まれていますが、\fIfile2\fR には含まれていません。
 .RE
 
@@ -63,8 +63,8 @@
 .na
 \fB+ \fIattribute2\fR=\fIvalue2\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 この \fIattribute\fR,\fIvalue\fR は \fIfile2\fR に含まれていますが、\fIfile1\fR には含まれていません。
 .RE
 
@@ -74,15 +74,26 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-i\fR \fIattribute\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 比較中に \fIattribute\fR が存在した場合は、無視します。\fB-i\fR \fIhash\fR により、ファイルのハッシュ値を無視できます。このオプションを \fB-o\fR オプションとともに使用することはできません。このオプションは繰り返すことができます。
 .RE
 
@@ -92,8 +103,8 @@
 .na
 \fB\fB-o\fR \fIattribute\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 \fIattribute\fR の違いのみを報告します。このオプションを \fB-i\fR オプションとともに使用することはできません。このオプションは、アクション時に \fIattribute\fR に影響を与えないアクション変更をすべて省略します。
 .RE
 
@@ -103,15 +114,15 @@
 .na
 \fB\fB-v\fR \fIname\fR=\fIvalue\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 このバリアント値の違いのみを計算します。たとえば、\fBarch=sparc\fR の違いのみを計算します。このバリアントタグは、比較前にすべてのアクションについて削除されます。バリアントあたり 1 つの値のみを指定できます。このオプションは、異なるバリアントに対して繰り返すことができます。
 .RE
 
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -142,7 +153,7 @@
 .ad
 .RS 7n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
--- a/src/man/ja_JP/pkgfmt.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgfmt.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgfmt 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgfmt 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgfmt \- パッケージマニフェストの整形
 .SH 形式
@@ -22,14 +22,29 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.RS 10n
+.rt  
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-c\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 マニフェストが \fBpkgfmt\fR 形式で整形されているかどうかをチェックします。
 .RE
@@ -40,7 +55,7 @@
 .na
 \fB\fB-d\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 統合された形式で整形されたバージョンとのマニフェストの違いを表示します。
 .RE
@@ -51,7 +66,7 @@
 .na
 \fB\fB-u\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 80 文字で行を折り返しません。このオプションは、パッケージマニフェストに従来のテキスト処理ツールを適用する場合に有効です。
 .RE
@@ -59,7 +74,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -86,11 +101,11 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
--- a/src/man/ja_JP/pkglint.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkglint.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,14 +1,14 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkglint 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkglint 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkglint \- Image Packaging System パッケージ lint
 .SH 形式
 .LP
 .nf
-/usr/bin/pkglint [-c \fIdir\fR] [-r \fIuri\fR] [-p \fIregexp\fR]
-    [-f \fIrcfile\fR] [-b \fIbuild_no\fR] [-v]
-    [-l \fIuri\fR] | \fImanifest\fR ...
+/usr/bin/pkglint [-c \fIcache_dir\fR] [-r \fIrepo_uri\fR] [-p \fIregexp\fR]
+    [-f \fIconfig_file\fR] [-b \fIbuild_no\fR] [-v]
+    [-l \fIlint_uri\fR] | \fImanifest\fR ...
 .fi
 
 .LP
@@ -22,7 +22,7 @@
 \fBpkglint\fR は、必要に応じて別のリポジトリを参照しながら、1 つ以上のパッケージマニフェストに対して一連のチェックを実行します。
 .sp
 .LP
-\fBpkglint\fR は、パッケージ公開前の、パッケージ作成処理中に使用するべきです。\fBpkglint\fR は、マニフェストに対して、\fBpkgsend\fR(1) または \fBpkg.depotd\fR(1M) の通常動作中に実行するには負荷が大きすぎる可能性のある徹底的なテストを実行します。\fBpkglint\fR のチェックには、重複したアクション、欠落した属性、および異常なファイルアクセス権に対するテストが含まれます。
+\fBpkglint\fR は、パッケージ公開前の、パッケージ作成処理中に使用するべきです。\fBpkglint\fR は、マニフェストに対して、\fBpkgsend\fR または \fBpkg.depotd\fR の通常動作中に実行するには負荷が大きすぎる可能性のある徹底的なテストを実行します。\fBpkglint\fR のチェックには、重複したアクション、欠落した属性、および異常なファイルアクセス権に対するテストが含まれます。
 .sp
 .LP
 lint のためのマニフェストは、コマンド行で、スペースで区切られたローカルファイルのリストとして渡すことができます。または、リポジトリからマニフェストを取得できます。
@@ -34,7 +34,7 @@
 \fBpkglint\fR の以降の呼び出しではキャッシュディレクトリを再利用できるため、\fB-r\fR または \fB-l\fR 引数はすべて省略できます。
 .sp
 .LP
-\fBpkglint\fR では、キャッシュディレクトリ内のパブリッシャーを構成するためのサポートが制限されています。これらのイメージに対して、より複雑なパブリッシャーの構成を実行するには、\fBpkg\fR(1) を使用します。
+\fBpkglint\fR では、キャッシュディレクトリ内のパブリッシャーを構成するためのサポートが制限されています。これらのイメージに対して、より複雑な発行元の構成を実行するには、\fBpkg\fR を使用します。
 .sp
 .LP
 \fBpkglint\fR では、パッケージ作成者は、特定のマニフェストまたはアクションに対するチェックをバイパスできます。\fBTrue\fR に設定された属性 \fBpkg.linted\fR を含むマニフェストまたはアクションでは、そのマニフェストまたはアクションに対する lint 出力は生成されません。
@@ -50,15 +50,30 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-h\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-b\fR \fIbuild_no\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 lint および参照リポジトリからの lint 中に使用されるパッケージのリストを絞り込むために使用されるビルド番号を指定します。\fB-b\fR オプションが指定されていない場合は、最新バージョンのパッケージが使用されます。\fBversion.pattern \fR 設定プロパティーも参照してください。
 .RE
 
@@ -68,8 +83,8 @@
 .na
 \fB\fB-c\fR \fIcache_dir\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 lint および参照リポジトリからのパッケージのメタデータをキャッシュするために使用されるローカルディレクトリを指定します。
 .RE
 
@@ -79,8 +94,8 @@
 .na
 \fB\fB-l\fR \fIlint_uri\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 lint リポジトリの場所を表す URI を指定します。HTTP ベースとファイルシステムベースの両方の公開がサポートされています。\fB-l\fR を指定する場合は、\fB-c\fR も指定する必要があります。
 .RE
 
@@ -90,8 +105,8 @@
 .na
 \fB\fB-L\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 既知の lint チェックと除外された lint チェックを一覧表示してから終了します。各チェックの短縮名と説明を表示します。\fB-v\fR フラグと組み合わせる場合は、説明の代わりに、このチェックを実装するメソッドを表示します。
 .RE
 
@@ -101,8 +116,8 @@
 .na
 \fB\fB-f\fR \fIconfig_file\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 \fIconfig_file\fR 構成ファイルを使用して \fBpkglint\fR セッションを構成します。
 .RE
 
@@ -112,8 +127,8 @@
 .na
 \fB\fB-p\fR \fIregexp\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 lint リポジトリからチェックされるパッケージのリストを絞り込むために使用される正規表現を指定します。参照リポジトリからはすべてのマニフェストがロードされ (\fB-b\fR が指定されている場合は、その値に一致すると仮定)、このパターンは無視されます。
 .RE
 
@@ -123,8 +138,8 @@
 .na
 \fB\fB-r\fR \fIrepo_uri\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 参照リポジトリの場所を表す URI を指定します。\fB-r\fR を指定する場合は、\fB-c\fR も指定する必要があります。
 .RE
 
@@ -134,22 +149,11 @@
 .na
 \fB\fB-v\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 \fBpkglint\fR を冗長モードで実行し、構成ファイル内の \fBlog_level\fR 設定をすべて上書きします。
 .RE
 
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR or \fB-?\fR\fR
-.ad
-.RS 18n
-.rt  
-使用方法に関するメッセージを表示します。
-.RE
-
 .SH ファイル
 .sp
 .LP
@@ -160,8 +164,8 @@
 .na
 \fB\fBlog_level\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 lint メッセージを発行する最小のレベル。このレベルより低い lint メッセージは破棄されます。デフォルト値は \fBINFO\fR です。
 .sp
 ログレベルを最小のレベルからもっとも重大なレベルの順に示すと、\fBDEBUG\fR、\fBINFO\fR、\fBWARNING\fR、\fBERROR\fR、\fBCRITICAL\fR になります。
@@ -173,8 +177,8 @@
 .na
 \fB\fBdo_pub_checks\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 \fBTrue\fR の場合は、公開されたパッケージにとってのみ意味がある可能性のあるチェックを実行します。デフォルト値は \fBTrue\fR です。
 .RE
 
@@ -184,9 +188,9 @@
 .na
 \fB\fBpkglint.ext.\fR*\fR
 .ad
-.RS 24n
-.rt  
-\fBpkglint\fR のプラグインメカニズムを使用すると、実行時に lint モジュールを追加できます。\fBpkglint.ext.\fR で始まるキーはすべて、完全に指定された Python モジュールである必要のある値を取ります。詳細は、「開発者」の節を参照してください。
+.sp .6
+.RS 4n
+\fBpkglint\fR のプラグインメカニズムを使用すると、実行時に lint モジュールを追加できます。\fBpkglint.ext.\fR で始まるキーはすべて、完全に指定された Python モジュールである必要のある値を取ります。詳細は、「開発者」のセクションを参照してください。
 .RE
 
 .sp
@@ -195,8 +199,8 @@
 .na
 \fB\fBpkglint.exclude\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 実行されるチェックのセットから省略する、完全に指定された Python モジュール、クラス、または関数名のスペースで区切られたリスト。
 .RE
 
@@ -206,8 +210,8 @@
 .na
 \fB\fBuse_progress_tracker\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 \fBTrue\fR の場合は、lint の実行中にマニフェストに対する処理を繰り返すときに進捗トラッカーを使用します。デフォルト値は \fBTrue\fR です。
 .RE
 
@@ -217,8 +221,8 @@
 .na
 \fB\fBversion.pattern\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 lint の対象となるビルド番号を指定するときに使用されるバージョンのパターン (\fB-b\fR)。構成ファイルで指定されていない場合、\fB-b\fR オプションはパターン \fB*,5.11-0.\fR を使用します。これは、ブランチ接頭辞が 0 である 5.11 ビルドのすべてのコンポーネントに一致します。
 .RE
 
@@ -318,7 +322,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -345,11 +349,11 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
@@ -385,7 +389,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkg\fR(1), \fBpkg.depotd\fR(1M), \fBpkgsend \fR(1), \fBpkg\fR(5)
+\fBpkg\fR(1), \fBpkg.depotd\fR(1M), \fBpkgsend\fR(1), \fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pkgmerge.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgmerge.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgmerge 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgmerge 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgmerge \- Image Packaging System パッケージマージユーティリティー
 .SH 形式
@@ -24,7 +24,22 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
@@ -33,7 +48,7 @@
 .ad
 .sp .6
 .RS 4n
-マージされたパッケージを公開する先のターゲットリポジトリのファイルシステムのパスまたは URI。このターゲットリポジトリはすでに存在している必要があります。新しいリポジトリは、\fBpkgrepo\fR(1) を使用して作成できます。
+マージされたパッケージを公開する先のターゲットリポジトリのファイルシステムのパスまたは URI を指定します。このターゲットリポジトリはすでに存在している必要があります。新しいリポジトリは、\fBpkgrepo\fR を使用して作成できます。
 .RE
 
 .sp
@@ -55,18 +70,7 @@
 .ad
 .sp .6
 .RS 4n
-このソースのパッケージに使用するバリアント名および値。そのあとに、パッケージを取得する元のソースリポジトリまたはパッケージアーカイブのファイルシステムのパスまたは URI が続きます。複数のバリアントをコンマで区切って指定できます。すべてのソースに対して同じバリアントを指定する必要があります。このオプションは複数回指定できます。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR or \fB-?\fR\fR
-.ad
-.sp .6
-.RS 4n
-使用方法に関するメッセージを表示します。
+このソースのパッケージに使用するバリアント名および値、そのあとに、パッケージを取得する元のソースリポジトリまたはパッケージアーカイブのファイルシステムのパスまたは URI を指定します。複数のバリアントをコンマで区切って指定できます。すべてのソースに対して同じバリアントを指定する必要があります。このオプションは複数回指定できます。
 .RE
 
 .SH 環境
@@ -340,7 +344,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -360,18 +364,18 @@
 .ad
 .RS 6n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
--- a/src/man/ja_JP/pkgmogrify.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgmogrify.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgmogrify 1 "2011 年 8 月 30 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgmogrify 1 "2012 年 6 月 4 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgmogrify \- Image Packaging System マニフェスト変換ツール
 .SH 形式
@@ -39,16 +39,31 @@
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-D\fR \fIname\fR=\fIvalue\fR\fR
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
 .ad
 .sp .6
 .RS 4n
-\fIname\fR を値 \fIvalue\fR とともにマクロとして定義します。マクロは、入力ファイル内で \fB$(macro)\fR として指定されます。置換は、それ以上の変換が見つからなくなるまで繰り返されます。一般的な語法には次のものがあります。
+使用方法に関するメッセージを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-D\fR \fImacro\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fImacro\fR を値 \fIvalue\fR とともにマクロとして定義します。マクロは、入力ファイル内で \fB$(macro)\fR として指定されます。置換は、それ以上の変換が見つからなくなるまで繰り返されます。一般的な語法には次のものがあります。
 .RS +4
 .TP
 .ie t \(bu
@@ -83,7 +98,7 @@
 .ne 2
 .mk
 .na
-\fB\fB-I\fR \fIinclude_directory\fR\fR
+\fB\fB-I\fR \fIincludedir\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -134,17 +149,6 @@
 出力マニフェストに変換の効果を示すコメントを書き込みます。この情報がデバッグに役立つことがあります。
 .RE
 
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR or \fB-?\fR\fR
-.ad
-.sp .6
-.RS 4n
-使用方法に関するメッセージを表示します。
-.RE
-
 .SH 埋め込みの指令
 .sp
 .LP
@@ -181,13 +185,13 @@
 .sp
 .in +2
 .nf
-[\fIaction-type\fR ... ] [\fIattribute\fR=<\fIvalue-regexp\fR> ...]
+[\fIaction-name\fR ... ] [\fIattribute\fR=<\fIvalue-regexp\fR> ...]
 .fi
 .in -2
 
 .sp
 .LP
-指定された \fIaction-types\fR のいずれかが一致する必要があります。指定された \fIattributes\fR のすべてが一致する必要があります。使用されている正規表現の構文は Python の構文です。Python 正規表現の構文については、コマンド \fBpydoc re\fR を使用するか、または \fBhttp://docs.python.org/dev/howto/regex.html\fR にあるより完全なドキュメントを参照してください。正規表現は先頭に固定され、末尾には固定されません。そのため、ファイルを拡張子で照合する正規表現には先頭に \fB\&.*\fR を含める必要があり、さらに末尾には \fB$\fR を含めるようにしてください。
+指定された \fIaction-name\fR の少なくとも 1 つが一致する必要があります。指定されたすべての \fIattribute\fR が一致する必要があります。アクションの名前と属性が、\fBpkg\fR(5) マニュアルページの「アクション」に一覧表示されます。使用されている正規表現の構文は Python の構文です。Python 正規表現の構文については、コマンド \fBpydoc re\fR を使用するか、または \fBhttp://docs.python.org/dev/howto/regex.html\fR にあるより完全なドキュメントを参照してください。正規表現は先頭に固定され、末尾には固定されません。そのため、ファイルを拡張子で照合する正規表現には先頭に \fB\&.*\fR を含める必要があり、さらに末尾には \fB$\fR を含めるようにしてください。
 .sp
 .LP
 複数の条件をスペースで区切って指定できます。
@@ -316,7 +320,7 @@
 .RE
 .sp
 .LP
-次の 3 つの合成属性は、\fBpkg\fR(1) で使用されるものに似ています。
+次の 3 つの合成属性は、\fBpkg\fR で使用されるものに似ています:
 .RS +4
 .TP
 .ie t \(bu
@@ -333,7 +337,7 @@
 .TP
 .ie t \(bu
 .el o
-\fBaction.name\fR は、アクションタイプの名前を参照します。
+\fBaction.name\fR は、アクションの名前を参照します。
 .RE
 .sp
 .LP
@@ -349,7 +353,7 @@
 これは、パッケージ属性をアクション属性であるかのように参照するためだけでなく、これらの属性を照合したり、一時的に変更したりするためにも有効です。したがって、これらの状況では、合成アクション名 \fBpkg\fR を (\fBpkgmogrify\fR のコンテキストでのみ) 使用できます。
 .sp
 .LP
-\fBpkgmogrify\fR がコマンド行で指定されたマニフェストの読み取りを完了し、そのマニフェストで \fBpkg.fmri\fR パッケージ属性が定義されている場合、\fBpkgmogrify\fR はこの合成アクション \fBpkg\fR を作成します。属性はパッケージの属性になります。その後、\fB<transform>\fR 指令は、ほかのアクションタイプと同様に、このアクションに照合できます。
+\fBpkgmogrify\fR がコマンド行で指定されたマニフェストの読み取りを完了し、そのマニフェストで \fBpkg.fmri\fR パッケージ属性が定義されている場合、\fBpkgmogrify\fR はこの合成アクション \fBpkg\fR を作成します。属性はパッケージの属性になります。その後、\fB<transform>\fR 指令は、ほかのアクションに照合できるのと同様に、このアクションに照合できます。
 .sp
 .LP
 \fBpkg\fR アクションに対する操作は、メモリー内でのみ実行されるために、出力されたマニフェストに直接影響を与えないという点で特殊です。たとえば、\fBadd\fR、\fBdefault\fR、または \fBset\fR 操作を使用して \fBpkg\fR アクションに属性を設定しようとしても、照合するほかの \fB<transform>\fR 指令では使用可能であるにもかかわらず、\fBset\fR アクションがマニフェストに追加されません。\fBpkg\fR アクションに対して \fBemit\fR を実行しようとすると、エラーが発生します。パッケージ属性を追加するには、代わりに \fBset\fR アクションに対して \fBemit\fR を実行します。
@@ -535,7 +539,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -562,11 +566,11 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
@@ -587,8 +591,8 @@
 .na
 \fB\fB/usr/share/pkg/transforms\fR\fR
 .ad
-.RS 29n
-.rt  
+.sp .6
+.RS 4n
 このディレクトリには、ファセット、アクチュエータ、およびその他の属性を設定するために役立つ変換を含むファイルが入っています。
 .RE
 
--- a/src/man/ja_JP/pkgrecv.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgrecv.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgrecv 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgrecv 1 "2012 年 6 月 11 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgrecv \- Image Packaging System 内容取得ユーティリティー
 .SH 形式
@@ -19,19 +19,33 @@
 .SH 機能説明
 .sp
 .LP
-\fBpkgrecv\fR を使用すると、ユーザーは \fBpkg\fR(5) リポジトリまたはパッケージアーカイブからパッケージを取得できます。また、\fBpkgrecv\fR はオプションで、取得されたパッケージを別のパッケージリポジトリに再公開したり、アーカイブしたりすることもできます。デフォルトでは、パッケージは \fBpkg\fR(1)、\fBpkg.depotd\fR(1M)、およびパッケージ公開ツールでの使用に適したパッケージリポジトリ形式で取得されます。
+\fBpkgrecv\fR を使用すると、ユーザーは \fBpkg\fR(5) リポジトリまたはパッケージアーカイブからパッケージを取得できます。また、\fBpkgrecv\fR はオプションで、取得されたパッケージを別のパッケージリポジトリに再公開したり、アーカイブしたりすることもできます。デフォルトでは、パッケージは \fBpkg\fR、\fBpkg.depotd\fR、およびパッケージ公開ツールでの使用に適したパッケージリポジトリ形式で取得されます。
+.sp
+.LP
+\fBpkgrecv\fR 操作後に、リポジトリに対して \fBpkgrepo refresh\fR または \fBpkgrepo rebuild\fR を実行し、検索インデックスを構築します。
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-h\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
 .ne 2
 .mk
 .na
 \fB\fB-a\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 取得されたパッケージデータを、\fB-d\fR で指定された場所にある \fBpkg\fR(5) アーカイブ内に格納します。このファイルがすでに存在していてはいけません。このオプションは、ファイルシステムベースの出力先の場合にのみ使用できます。必須ではありませんが、\fB\&.p5p\fR のファイル拡張子 (たとえば、\fBarchive.p5p\fR) を使用することを強くお勧めします。このオプションを \fB--raw\fR と組み合わせることはできません。
 .RE
 
@@ -41,31 +55,20 @@
 .na
 \fB\fB-c\fR \fIcache_dir\fR\fR
 .ad
-.RS 19n
-.rt  
-ダウンロードされた内容をキャッシュするために使用されるディレクトリのパス。このディレクトリが指定されていない場合は、クライアントによってキャッシュディレクトリが自動的に選択されます。ダウンロードが中断されたときに、キャッシュディレクトリが自動的に選択されていた場合は、このオプションを使用してダウンロードを再開します。一時的なデータストレージに使用される場所を設定する方法についての詳細は、下の「環境変数」の節を参照してください。
+.sp .6
+.RS 4n
+ダウンロードされた内容をキャッシュするために使用されるディレクトリのパスを指定します。このディレクトリが指定されていない場合は、クライアントによってキャッシュディレクトリが自動的に選択されます。ダウンロードが中断されたときに、キャッシュディレクトリが自動的に選択されていた場合は、このオプションを使用してダウンロードを再開します。一時的なデータストレージに使用される場所を設定する方法についての詳細は、下の「環境変数」のセクションを参照してください。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-d\fR \fIpath_or_uri\fR\fR
+\fB\fB-d\fR (\fIpath\fR|\fI dest_uri\fR)\fR
 .ad
-.RS 19n
-.rt  
-パッケージを再公開する先のターゲットのファイルシステムのパスまたは URI。このターゲットはすでに存在する必要があります。新しいリポジトリは、\fBpkgrepo\fR(1) を使用して作成できます。\fB-a\fR が指定されている場合、ターゲットは新しいパッケージアーカイブであると見なされます。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fB-h\fR\fR
-.ad
-.RS 19n
-.rt  
-使用方法に関するメッセージを表示します。
+.sp .6
+.RS 4n
+パッケージを再公開する先のターゲットのファイルシステムのパスまたは URI を指定します。\fB-a\fR が指定されている場合、ターゲットはまだ存在しない新しいパッケージアーカイブです。指定されていない場合、ターゲットはすでに存在するパッケージリポジトリである必要があります。新しいリポジトリは、\fBpkgrepo\fR を使用して作成できます。
 .RE
 
 .sp
@@ -74,9 +77,9 @@
 .na
 \fB\fB-k\fR\fR
 .ad
-.RS 19n
-.rt  
-取得されたパッケージの内容を圧縮されたままにします。このオプションは、再公開時には無視されます。圧縮されたパッケージの内容を \fBpkgsend\fR(1) で使用しないようにしてください。
+.sp .6
+.RS 4n
+取得されたパッケージの内容を圧縮されたままにします。このオプションは、再公開時には無視されます。圧縮されたパッケージの内容を \fBpkgsend\fR で使用しないようにしてください。
 .RE
 
 .sp
@@ -85,17 +88,17 @@
 .na
 \fB\fB-m\fR \fImatch\fR\fR
 .ad
-.RS 19n
-.rt  
-次の値を使用して照合動作を制御します。
+.sp .6
+.RS 4n
+次の値を使用して、マッチング動作を制御します:
 .sp
 .ne 2
 .mk
 .na
 \fB\fBall-timestamps\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 最新のタイムスタンプだけでなく、一致するすべてのタイムスタンプを含めます (\fBall-versions\fR が暗黙的に指定されます)。
 .RE
 
@@ -105,8 +108,8 @@
 .na
 \fB\fBall-versions\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 最新のバージョンだけでなく、一致するすべてのバージョンを含めます。
 .RE
 
@@ -118,8 +121,8 @@
 .na
 \fB\fB-n\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 変更を行うことなく、試験実行を行います。
 .RE
 
@@ -129,8 +132,8 @@
 .na
 \fB\fB-r\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 提供されたパッケージリストのすべての依存関係を再帰的に取得します。
 .RE
 
@@ -138,21 +141,21 @@
 .ne 2
 .mk
 .na
-\fB\fB-s\fR \fIsrc_repo_uri\fR\fR
+\fB\fB-s\fR \fIsrc_uri\fR\fR
 .ad
-.RS 19n
-.rt  
-パッケージデータ受信先の \fBpkg\fR(5) リポジトリまたはパッケージアーカイブの場所を表す URI。
+.sp .6
+.RS 4n
+パッケージデータ受信先の \fBpkg\fR(5) リポジトリまたはパッケージアーカイブの場所を表す URI を指定します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--cert\fR \fIfile\fR\fR
+\fB\fB--cert\fR \fIcertfile\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 HTTPS リポジトリからのパッケージ取得に使用するクライアント SSL 証明書ファイルを指定します。
 .RE
 
@@ -160,10 +163,10 @@
 .ne 2
 .mk
 .na
-\fB\fB--key\fR \fIfile\fR\fR
+\fB\fB--key\fR \fIkeyfile\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 HTTPS リポジトリからのパッケージ取得に使用するクライアント SSL キーファイルを指定します。
 .RE
 
@@ -173,8 +176,8 @@
 .na
 \fB\fB--newest\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 指定されたリポジトリから使用可能な最新バージョンのパッケージを一覧表示し、終了します (\fB-s\fR を除くその他のオプションはすべて無視されます)。
 .RE
 
@@ -184,8 +187,8 @@
 .na
 \fB\fB--raw\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 raw パッケージデータを取得し、\fB-d\fR で指定された場所に、幹およびバージョンごとの一連のディレクトリ構造内に格納します。このオプションは、ファイルシステムベースの出力先の場合にのみ使用できます。このパッケージデータを使用すると、一般にはファイルの内容を修正するか、または追加のパッケージメタデータを提供することによって、パッケージを便利に変更して再公開することができます。このオプションを \fB-a\fR と組み合わせることはできません。
 .RE
 
@@ -200,10 +203,9 @@
 .in +2
 .nf
 $ \fBpkgrecv -s http://test --newest\fR
-pkg:/[email protected],5.11-0.79:20080221T125720Z
-pkg:/[email protected],5.11-0.79:20080221T123955Z
-pkg:/[email protected],5.11-0.79:20080221T125728Z
-pkg:/[email protected],5.11-0.79:20080221T125730Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z
+pkg://solaris/system/library/[email protected],5.11-0.175.1.0.0.7.1234:20120109T215840Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190432Z
 .fi
 .in -2
 .sp
@@ -212,17 +214,20 @@
 \fB例 2 \fRraw パッケージデータを取得する
 .sp
 .LP
-例 1 の \fBSUNWlibC\fR、\fBSUNWfreetype\fR、および \fBSUNWlibm\fR パッケージを、\fBpkgsend include\fR での使用に適した形式で受信します。
+例 1 から \fBc++-runtime\fR パッケージを \fBpkgsend publish\fR で使用するために適した形式で受け取ります。
 
 .sp
 .in +2
 .nf
 $ \fBpkgrecv -s http://test \e\fR
-\[email protected],5.11-0.79:20080221T125720Z --raw\fR
[email protected],5.11-0.79:20080221T123955Z
[email protected],5.11-0.79:20080221T125728Z
-$ \fBls -d SUNW*\fR
-SUNWfreetype2  SUNWlibC       SUNWlibm
+\fB-d /local/repo --raw \e\fR
+\[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z\fR
+Processing packages for publisher solaris ...
+Retrieving and evaluating 1 package(s)...
+PROCESS       ITEMS     GET (MB)    SEND (MB)
+Completed       1/1      3.5/3.5      0.0/0.0
+$ \fBls /local/repo\fR
+pkg5.repository  publisher  system%2Flibrary%2Fc%2B%2B-runtime
 .fi
 .in -2
 .sp
@@ -231,12 +236,12 @@
 \fB例 3 \fRシステムから依存関係を取得する
 .sp
 .LP
-\fBtest\fR という名前のシステムから、パッケージ \fBSUNWvim\fR とそのすべての依存関係を受信します。
+\fBtest\fR という名前のシステムから、パッケージ \fBeditor/vim\fR とそのすべての依存関係を受け取ります。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -r SUNWvim\fR
+$ \fBpkgrecv -s http://test -d /local/repo -r editor/vim\fR
 .fi
 .in -2
 .sp
@@ -245,88 +250,97 @@
 \fB例 4 \fRすべてのバージョンを取得する
 .sp
 .LP
-\fBtest\fR という名前のシステムから、パッケージ \fBSUNWvim\fR のすべてのバージョンを受信します。
+\fBtest\fR という名前のシステムから、パッケージ \fBeditor/vim\fR のすべてのバージョンを受け取ります。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -m all-versions SUNWvim\fR
+$ \fBpkgrecv -s http://test -d /local/repo -m all-versions \e\fR
+\fBeditor/vim\fR
+Processing packages for publisher solaris ...
+Retrieving and evaluating 2 package(s)...
+PROCESS       ITEMS     GET (MB)    SEND(MB)
+Completed       2/2    16.7/16.7    44.9/44.9
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 5 \fRすべてのバージョンを取得し、ローカルに再公開する
+\fB例 5 \fRすべてのバージョンを取得し、リモートから再公開する
 .sp
 .LP
-\fBtest\fR という名前のシステムから、パッケージ \fBSUNWvim\fR のすべてのバージョンを受信し、それをローカルリポジトリに再公開します。
+\fBtest\fR という名前のシステムから、パッケージ \fBlibrary/zlib\fR のすべてのバージョンを受け取り、それを \fBremote\fR という名前のシステム上のリモートリポジトリに再公開します。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -d /local/repo SUNWvim\fR
+$ \fBpkgrecv -s http://test -d http://remote:10000 \e\fR
+\fB-m all-versions library/zlib\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 6 \fRすべてのバージョンを取得し、リモートから再公開する
+\fB例 6 \fRリポジトリから依存関係を取得する
 .sp
 .LP
-\fBtest\fR という名前のシステムから、パッケージ \fBSUNWzlib\fR のすべてのバージョンを受信し、それを \fBremote\fR という名前のシステム上のリモートリポジトリに再公開します。
+\fB/export/repo\fR にあるリポジトリから、パッケージ \fBeditor/gnu-emacs\fR とそのすべての依存関係を受け取ります。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -d http://remote:10000 SUNWzlib\fR
+$ \fBpkgrecv -s /export/repo -d /local/repo -r editor/gnu-emacs\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 7 \fRリポジトリから依存関係を取得する
+\fB例 7 \fR追加パッケージおよび変更された内容の取得
 .sp
 .LP
-\fB/export/repo\fR にあるリポジトリから、パッケージ \fBSUNWemacs\fR とそのすべての依存関係を受信します。
+まだ存在しないすべてのパッケージおよびすべての変更済みの内容を、\fBhttp://pkg.oracle.com/solaris/release/\fR にあるリポジトリから \fB/export/repoSolaris11\fR にあるリポジトリに受信します。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s /export/repo -r SUNWemacs\fR
+$ \fBpkgrecv -s http://pkg.oracle.com/solaris/release/ \e\fR
+\fB-d /export/repoSolaris11 -m all-timestamps '*'\fR
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+まだ存在しないすべてのパッケージおよびすべての変更済みの内容を、\fBhttp://pkg.oracle.com/solaris/support/\fR にあるセキュアなリポジトリから \fB/export/repoSolaris11\fR にあるリポジトリに受信します。
+
+.sp
+.in +2
+.nf
+$ \fBpkgrecv -s http://pkg.oracle.com/solaris/support/ \e\fR
+\fB-d /export/repoSolaris11 -m all-timestamps \e\fR
+\fB--key /var/pkg/ssl/Oracle_Solaris_11_Support.key.pem \e\fR
+\fB--cert /var/pkg/ssl/Oracle_Solaris_11_Support.certificate.pem '*'\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 8 \fR追加のパッケージを取得する
+\fB例 8 \fRパッケージアーカイブを作成する
 .sp
 .LP
-\fBhttp://example.com:10000\fR にあるリポジトリから、まだ存在しないすべてのパッケージを受信します。
+\fBhttp://example.com:10000\fR にあるリポジトリから、パッケージ \fBeditor/gnu-emacs\fR とそのすべての依存関係を含むパッケージアーカイブを作成します。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://example.com:10000 -d /my/pkg/repo '*'\fR
+$ \fBpkgrecv -s http://example.com:10000 -d /my/emacs.p5p -a \e\fR
+\fB-r editor/gnu-emacs\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB例 9 \fRパッケージアーカイブを作成する
-.sp
-.LP
-\fBhttp://example.com:10000\fR にあるリポジトリから、パッケージ \fBSUNWemacs\fR とそのすべての依存関係を含むパッケージアーカイブを作成します。
-
-.sp
-.in +2
-.nf
-$ \fBpkgrecv -s http://example.com:10000 -d /my/emacs.p5p -a -r SUNWemacs\fR
-.fi
-.in -2
-.sp
-
-.LP
-\fB例 10 \fRパッケージをアーカイブからリポジトリにコピーする
+\fB例 9 \fRパッケージをアーカイブからリポジトリにコピーする
 .sp
 .LP
 パッケージアーカイブ内のすべてのパッケージを \fB/export/repo\fR にある既存のリポジトリにコピーします。
@@ -379,7 +393,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -399,18 +413,18 @@
 .ad
 .RS 6n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
@@ -421,7 +435,7 @@
 .ad
 .RS 6n
 .rt  
-複数の操作が要求されましたが、その一部しか成功しませんでした。
+複数の操作が要求されましたが、それらの一部のみが成功しました。
 .RE
 
 .sp
--- a/src/man/ja_JP/pkgrepo.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgrepo.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgrepo 1 "2011 年 8 月 30 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgrepo 1 "2012 年 6 月 22 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgrepo \- Image Packaging System リポジトリ管理ユーティリティー
 .SH 形式
@@ -16,7 +16,7 @@
 
 .LP
 .nf
-/usr/bin/pkgrepo get [-F \fIformat\fR] [-p \fIpublisher\fR ...]
+/usr/bin/pkgrepo get [-F \fIformat\fR] [-H] [-p \fIpublisher\fR ...]
     -s \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]
 .fi
 
@@ -53,7 +53,12 @@
 .LP
 .nf
 /usr/bin/pkgrepo set [-p \fIpublisher\fR] -s \fIrepo_uri_or_path\fR
-    \fIsection/property\fR=[\fIvalue\fR] ... or
+    \fIsection/property\fR=[\fIvalue\fR]
+.fi
+
+.LP
+.nf
+/usr/bin/pkgrepo set [-p \fIpublisher\fR] -s \fIrepo_uri_or_path\fR
     \fIsection/property\fR=([\fIvalue\fR]) ...
 .fi
 
@@ -70,31 +75,35 @@
 .SH 機能説明
 .sp
 .LP
-\fBpkgrepo\fR を使用すると、\fBpkg\fR(5) パッケージリポジトリの作成および管理を行うことができます。パッケージリポジトリは、\fBpkg\fR(1) や、\fBpkgsend\fR(1) または \fBpkgrecv\fR(1) などの公開クライアントがパッケージデータを格納したり取得したりできるようにするための、定義済みの一連のディレクトリおよびファイルです。さらに、パッケージリポジトリへのネットワークベースのアクセスが必要な場合、\fBpkg.depotd\fR(1m) は、クライアントにパッケージデータを格納したり取得したりするためのリポジトリへのアクセスを提供できます。
+\fBpkgrepo\fR を使用すると、\fBpkg\fR(5) パッケージリポジトリの作成および管理を行うことができます。パッケージリポジトリは、\fBpkg\fR や、\fBpkgsend\fR または \fBpkgrecv\fR などの公開クライアントがパッケージデータを格納したり取得したりできるようにするための、定義済みの一連のディレクトリおよびファイルです。さらに、パッケージリポジトリへのネットワークベースのアクセスが必要な場合、\fBpkg.depotd\fR は、クライアントにパッケージデータを格納したり取得したりするためのリポジトリへのアクセスを提供できます。
 .SH オプション
 .sp
 .LP
-次のオプションがサポートされています。
+サポートしているオプションは、次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR or \fB-?\fR\fR
+\fB\fB-?\fR\fR
 .ad
-.RS 16n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 使用方法に関するメッセージを表示します。
 .RE
 
 .SH サブコマンド
 .sp
 .LP
-次のサブコマンドがサポートされています。
+サポートされているサブコマンドは次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fBcreate [\fB--version\fR \fIver\fR] \fI uri_or_path\fR\fR\fR
+\fB\fBpkgrepo create\fR [\fB--version\fR \fI ver\fR] \fIuri_or_path\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -102,22 +111,37 @@
 .sp
 このサブコマンドは、ファイルシステムベースのリポジトリでのみ使用できます。
 .sp
-\fB--version\fR が指定されている場合は、指定されたバージョンと互換性がある形式でリポジトリを作成します。デフォルトでは、バージョン 4 のリポジトリが作成されます。サポートされるバージョンは次のとおりです。
+.ne 2
+.mk
+.na
+\fB\fB--version\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定されたバージョンと互換性がある形式でリポジトリを作成します。デフォルトでは、バージョン 4 のリポジトリが作成されます。サポートされるバージョンは次のとおりです。
 .sp
+.ne 2
+.mk
+.na
+\fB3\fR
+.ad
+.RS 5n
+.rt  
+1 つのパブリッシャー、カタログバージョン 1、および検索バージョン 1 でのパッケージの格納をサポートします。
+.RE
 
 .sp
-.TS
-tab();
-lw(.33i) lw(5.17i) 
-lw(.33i) lw(5.17i) 
-.
-3T{
-1 つのパブリッシャー、カタログバージョン 1、および検索バージョン 1 でのパッケージの格納をサポートします。
-T}
-4T{
+.ne 2
+.mk
+.na
+\fB4\fR
+.ad
+.RS 5n
+.rt  
 複数のパブリッシャー、カタログバージョン 1、および検索バージョン 1 でのパッケージの格納をサポートします。
-T}
-.TE
+.RE
+
+.RE
 
 .RE
 
@@ -125,11 +149,11 @@
 .ne 2
 .mk
 .na
-\fB\fBadd-publisher \fB-s\fR \fIrepo_uri_or_path \fR \fIpublisher\fR ...\fR\fR
+\fB\fBpkgrepo add-publisher\fR \fB-s\fR \fI repo_uri_or_path\fR \fIpublisher\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-指定されたパブリッシャーをリポジトリに追加します。新しいパブリッシャーにパッケージや内容は含まれていません。
+指定された発行元をリポジトリに追加します。新しいパブリッシャーにパッケージや内容は含まれていません。
 .sp
 このサブコマンドは、バージョン 4 のファイルシステムベースのリポジトリでのみ使用できます。
 .RE
@@ -138,11 +162,11 @@
 .ne 2
 .mk
 .na
-\fB\fBget [\fB-F\fR \fIformat\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR [\fIsection/property\fR ...]\fR\fR
+\fB\fBpkgrepo get\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fI section/property\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-リポジトリまたはそのパブリッシャーのプロパティー情報を表示します。
+リポジトリまたはその発行元のプロパティー情報を表示します。
 .sp
 デフォルトでは、各プロパティーとその値が個別の行に出力されます。空の ASCII 文字列値は、二重引用符 (\fB""\fR) のペアで表されます。ASCII 文字列値内の次の Bourne シェルのメタキャラクタと、改行、スペース、およびタブは、バックスラッシュ文字 (\fB\e\fR) でエスケープする必要があります。
 .sp
@@ -152,43 +176,126 @@
 .fi
 .in -2
 
-「使用例」の節を参照してください。
+発行元とリポジトリプロパティーの表示例については、「使用例」セクションを参照してください。
+.sp
+プロパティーのリスト、および各プロパティーの目的と値については、下の \fBset\fR サブコマンドを参照してください。
 .sp
-指定できるプロパティーのリスト、および各プロパティーの目的と値については、下の \fBset\fR サブコマンドを参照してください。
-.sp
-\fB-F\fR が指定されている場合は、代替の出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fB json\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted \fR (読みやすい形式にされた JavaScript Object Notation) にできます。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+代替出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fBjson\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted\fR (読みやすい形式にされた JavaScript Object Notation) にできます。
+.RE
+
 .sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーのプロパティー情報を表示します。特殊な値 \fBall\fR により、すべてのパブリッシャーのプロパティーが表示されます。このオプションは複数回指定できます。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のプロパティー情報を表示します。特殊な値 \fBall\fR により、すべてのパブリッシャーのプロパティーが表示されます。このオプションは複数回指定できます。
+.RE
+
 .sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinfo [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR\fR\fR
+\fB\fIsection/property\fR\fR
 .ad
 .sp .6
 .RS 4n
-リポジトリで認識されているパッケージパブリッシャーのリストを表示します。このリストには、パブリッシャーごとのパッケージの数、パブリッシャーのパッケージデータが最後に更新された日時、およびパブリッシャーのパッケージデータのステータス (現在処理されているかどうかなど) が含まれます。
-.sp
-\fB-F\fR が指定されている場合は、代替の出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fBjson\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted\fR (読みやすい形式にされた JavaScript Object Notation) にできます。
+\fB publisher/prefix\fR や \fBrepository/version\fR などの、指定されたプロパティーの値のみを表示します。プロパティーの完全な一覧については、\fB set\fR サブコマンドを参照してください。
+.RE
+
+.RE
+
 .sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo info\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+リポジトリで認識されているパッケージ発行元のリストを表示します。このリストには、パブリッシャーごとのパッケージの数、パブリッシャーのパッケージデータが最後に更新された日時、およびパブリッシャーのパッケージデータのステータス (現在処理されているかどうかなど) が含まれます。
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーのデータのみが表示されます。指定されていない場合は、すべてのパブリッシャーのデータが表示されます。このオプションは複数回指定できます。
-.sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+代替出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fBjson\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted\fR (読みやすい形式にされた JavaScript Object Notation) にできます。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB list [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のデータのみを表示します。指定されていない場合は、すべてのパブリッシャーのデータが表示されます。このオプションは複数回指定できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo list\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fI pkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -196,62 +303,170 @@
 .sp
 デフォルトの出力では、最初の列にパッケージのパブリッシャーの名前が含まれます。2 番目の列にはパッケージの名前が含まれます。3 番目の列には、パッケージのステータスを示すフラグが含まれます。ステータス列の \fBo\fR の値は、パッケージが廃止されていることを示します。ステータス列の \fBr\fR の値は、パッケージの名前が変更されたことを示します (廃止の形態の 1 つです)。4 番目の列には、パッケージのリリースおよびブランチのバージョンが含まれます。リリースバージョンとブランチバージョンについては、\fBpkg\fR(5) を参照してください。
 .sp
-\fB-F\fR が指定されている場合は、代替の出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fBjson\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted\fR (読みやすい形式にされた JavaScript Object Notation) にできます。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+代替出力形式を指定します。\fIformat\fR の値は、\fBtsv\fR (Tab Separated Values)、\fBjson\fR (単一行としての JavaScript Object Notation)、または \fBjson-formatted\fR (読みやすい形式にされた JavaScript Object Notation) にできます。
+.RE
+
 .sp
-\fB-H\fR が指定されている場合は、リストのヘッダーを省略します。
+.ne 2
+.mk
+.na
+\fB\fB-H\fR \fR
+.ad
+.sp .6
+.RS 4n
+一覧からヘッダーを省略します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のパッケージのみを表示します。指定されていない場合は、すべてのパブリッシャーのパッケージが表示されます。このオプションは複数回指定できます。
+.RE
+
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーのパッケージのみが表示されます。指定されていない場合は、すべてのパブリッシャーのパッケージが表示されます。このオプションは複数回指定できます。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.RE
+
+.RE
+
 .sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB- -no-catalog\fR] [\fB--no-index\fR]\fR
+.ad
+.sp .6
+.RS 4n
+リポジトリ内に見つかったすべてのカタログ、検索、およびその他のキャッシュされた情報を破棄し、それをリポジトリの現在の内容に基づいて再作成します。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元についてのみ操作を実行します。指定されていない場合や、特殊な値 \fBall\fR が指定されている場合は、すべてのパブリッシャーについて操作が実行されます。このオプションは複数回指定できます。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrebuild [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR\fR
+\fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
 .RS 4n
-リポジトリ内に見つかったすべてのカタログ、検索、およびその他のキャッシュされた情報を破棄し、それをリポジトリの現在の内容に基づいて再作成します。
-.sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーについてのみ操作を実行します。指定されていない場合や、特殊な値 \fBall\fR が指定されている場合は、すべてのパブリッシャーについて操作が実行されます。このオプションは複数回指定できます。
+パッケージデータを再構築しません。
+.RE
+
 .sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
-.sp
-\fB--no-catalog\fR が指定されている場合は、パッケージデータを再構築しません。
-.sp
-\fB--no-index\fR が指定されている場合は、検索インデックスを再構築しません。
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+検索インデックスを再構築しません。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrefresh [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR\fR
+\fB\fBpkgrepo refresh\fR [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB- -no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
 リポジトリ内に見つかった新しいパッケージをすべてカタログ化し、すべての検索インデックスを更新します。これは、遅延公開 (\fBpkgsend\fR の \fB--no-catalog\fR または \fB--no-index\fR オプション) で使用されることを目的にしています。
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーについてのみ操作を実行します。指定されていない場合や、特殊な値 \fBall\fR が指定されている場合は、すべてのパブリッシャーについて操作が実行されます。このオプションは複数回指定できます。
-.sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
-.sp
-\fB--no-catalog\fR が指定されている場合は、新しいパッケージを追加しません。
-.sp
-\fB--no-index\fR が指定されている場合は、検索インデックスを更新しません。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元についてのみ操作を実行します。指定されていない場合や、特殊な値 \fBall\fR が指定されている場合は、すべてのパブリッシャーについて操作が実行されます。このオプションは複数回指定できます。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBremove [\fB-n\fR] [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR \fI pkg_fmri_pattern\fR ...\fR\fR
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
 .RS 4n
-リポジトリから、指定されたパターンに一致するパッケージを削除します。これらのパッケージが参照している、ほかのどのパッケージでも使用されていないすべてのファイルも削除されます。
+新しいパッケージを追加しません。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+検索インデックスを更新しません。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo remove\fR [\fB-n\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR \fIpkg_fmri_pattern\fR ...\fR
+.ad
+.sp .6
+.RS 4n
+リポジトリから、指定されたパターンに一致するパッケージ (これらのパッケージが参照している、ほかのどのパッケージでも使用されていないすべてのファイルを含む) を削除します。
 .LP
 注 - 
 .sp
@@ -265,29 +480,78 @@
 .RS 2
 この操作は元に戻せません。また、ほかのクライアントがそのリポジトリにアクセスしている間に使用すべきではありません。使用すると、それらのクライアントが取得操作中に失敗する可能性があります。
 .RE
-\fB-n\fR が指定されている場合は、パッケージを変更することなく、操作の試験実行を行います。終了する前に、削除されるパッケージのリストが表示されます。
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーの一致するパッケージのみを削除します。指定されていない場合は、すべてのパブリッシャーの一致するパッケージがすべて削除されます。このオプションは複数回指定できます。
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージの変更は行わずに試しに操作を実行します。終了する前に、削除されるパッケージのリストが表示されます。
+.RE
+
 .sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元の一致するパッケージのみを削除します。指定されていない場合は、すべてのパブリッシャーの一致するパッケージがすべて削除されます。このオプションは複数回指定できます。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset [\fB-p\fR \fIpublisher\fR] \fB- s\fR \fIrepo_uri_or_path\fR \fIsection/property \fR=[\fIvalue\fR] ... or \fIsection/property \fR=([\fIvalue\fR]) ...\fR\fR
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo set\fR [\fB-p\fR \fI publisher\fR] \fB-s\fR \fIrepo_uri_or_path\fR \fI section/property\fR=[\fIvalue\fR] ...\fR
+.ad
+.br
+.na
+\fB\fBset\fR [\fB-p\fR \fIpublisher\fR] \fB- s\fR \fIrepo_uri_or_path\fR \fIsection/property \fR=([\fIvalue\fR]) ...\fR
 .ad
 .sp .6
 .RS 4n
-リポジトリまたはパブリッシャーの指定されたプロパティーの値を設定します。
+リポジトリまたは発行元の指定されたプロパティーの値を設定します。
 .sp
 このサブコマンドは、ファイルシステムベースのリポジトリでのみ使用できます。
 .sp
-\fB-p\fR が指定されている場合は、指定されたパブリッシャーのプロパティーデータのみを設定します。パブリッシャーがまだ存在しない場合は、追加されます。特殊な値 \fBall\fR を使用すると、すべてのパブリッシャーのプロパティーを設定できます。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された発行元のプロパティーデータのみを設定します。パブリッシャーがまだ存在しない場合は、追加されます。特殊な値 \fBall\fR を使用すると、すべての発行元のプロパティーを設定できます。
+.RE
+
 .sp
-\fB-s\fR が指定されている場合は、指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
-.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定された URI またはファイルシステムのパスにあるリポジトリを操作します。
+.RE
+
 プロパティーと値は、次のいずれかの形式を使用して指定できます。
 .sp
 .ne 2
@@ -327,33 +591,11 @@
 .ne 2
 .mk
 .na
-\fB\fIpublisher\fR/\fIprefix\fR\fR
-.ad
-.sp .6
-.RS 4n
-デフォルトのパブリッシャーの名前を表す文字列。最初の文字は a-z、A-Z、または 0-9 である必要があります。文字列の残りの部分には、文字 0-9、-、.、a-z、および A-Z のみを含めることができます。この値は、複数のパブリッシャーのパッケージが存在する場合や、パッケージがリポジトリに公開されたときにパブリッシャーが指定されていない場合に使用すべきパブリッシャーを示します。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fIpublisher\fR/\fIsigning_ca_certs \fR\fR
+\fB\fBpublisher/prefix\fR\fR
 .ad
-.sp .6
-.RS 4n
-このパブリッシャーに使用すべき署名元の CA 証明書のハッシュを含む文字列のリスト。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fIpublisher\fR/\fIintermediate_certs \fR\fR
-.ad
-.sp .6
-.RS 4n
-このパブリッシャーに使用すべき中間証明書のハッシュを含む文字列のリスト。
+.RS 20n
+.rt  
+デフォルトのパブリッシャーの名前を表す文字列。最初の文字は a-z、A-Z、または 0-9 である必要があります。文字列の残りの部分には、文字 0-9、-、.、a-z、および A-Z のみを含めることができます。この値は、複数のパブリッシャーのパッケージが存在するとき、またはパッケージがリポジトリに公開されているが、パブリッシャーが指定されていないときに使用されるべきパブリッシャーを示します。
 .RE
 
 リポジトリバージョン 3 および 4 の場合は、リポジトリ内の個々のパブリッシャーの次のプロパティーを設定できます。
@@ -361,7 +603,7 @@
 .ne 2
 .mk
 .na
-\fB\fIpublisher\fR/\fIalias\fR\fR
+\fB\fBpublisher/alias\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -372,7 +614,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIcollection_type \fR\fR
+\fB\fBrepository/collection_type\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -387,7 +629,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIdescription \fR\fR
+\fB\fBrepository/description\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -398,7 +640,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIdetailed_url \fR\fR
+\fB\fBrepository/detailed_url\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -409,7 +651,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIlegal_uris \fR\fR
+\fB\fBrepository/legal_uris\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -420,7 +662,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fImirrors\fR\fR
+\fB\fBrepository/mirrors\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -431,7 +673,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIname\fR\fR
+\fB\fBrepository/name\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -442,7 +684,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIorigins\fR\fR
+\fB\fBrepository/origins\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -453,7 +695,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIrefresh_seconds \fR\fR
+\fB\fBrepository/refresh_seconds\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -464,7 +706,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIregistration_uri \fR\fR
+\fB\fBrepository/registration_uri\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -475,7 +717,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIrelated_uris \fR\fR
+\fB\fBrepository/related_uris\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -489,7 +731,18 @@
 .ne 2
 .mk
 .na
-\fB\fBversion\fR\fR
+\fB\fBpkgrepo help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo version\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -511,7 +764,7 @@
 \fB例 2 \fR情報を表示する
 .sp
 .LP
-パブリッシャーの概要と、リポジトリ内のパッケージの数を表示します。
+パブリッシャーのサマリーと、リポジトリ内のパッケージの数を表示します。
 
 .sp
 .in +2
@@ -560,12 +813,16 @@
 .sp
 .in +2
 .nf
-$ \fBpkgrepo get -s /my/repository\fR
-SECTION    PROPERTY VALUE
-publisher  prefix   ""
-repository version  4
+$ \fBpkgrepo get -s /export/repoSolaris11\fR
+SECTION    PROPERTY    VALUE
+publisher  prefix      solaris
+repository description Local\e copy\e of\e the\e Oracle\e Solaris\e 11\e repository
+repository name        Oracle\e Solaris\e 11
+repository version     4
 $ \fBpkgrepo get -s http://pkg.oracle.com/solaris/release/\fR
 SECTION    PROPERTY VALUE
+deployment content  s11_11-11
+deployment pubdate  20111102T222051Z
 publisher  prefix   solaris
 repository version  4
 .fi
@@ -582,7 +839,8 @@
 solaris   publisher  alias
 solaris   publisher  prefix           solaris
 solaris   repository collection-type  core
-solaris   repository description      This\e repository\e serves\e the\e Oracle\e Solaris\e 11\e Package\e repository.
+solaris   repository description      This\e repository\e serves\e the\e Oracle\e
+Solaris\e 11\e Package\e repository.
 solaris   repository legal-uris       ()
 solaris   repository mirrors          (http://pkg-cdn1.oracle.com/solaris.release/)
 solaris   repository name             Oracle\e Solaris\e 11\e Package\e Repository
@@ -628,7 +886,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -648,18 +906,18 @@
 .ad
 .RS 6n
 .rt  
-エラーが発生しました。
+エラーが発生した。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
-無効なコマンド行オプションが指定されました。
+無効なコマンド行オプションが指定された。
 .RE
 
 .sp
@@ -670,7 +928,7 @@
 .ad
 .RS 6n
 .rt  
-複数の操作が要求されましたが、その一部しか成功しませんでした。
+複数の操作が要求されましたが、それらの一部のみが成功しました。
 .RE
 
 .sp
@@ -717,7 +975,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkg\fR(1), \fBpkgrecv\fR(1), \fBpkgsend\fR(1), \fB pkg.depotd\fR(1M), \fBpkg\fR(5)
+\fBpkg\fR(1)、\fBpkgrecv\fR(1)、\fBpkgsend\fR(1)、\fBpkg.depotd\fR(1M)、\fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pkgsend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgsend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,59 +1,68 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgsend 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgsend 1 "2012 年 6 月 22 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgsend \- Image Packaging System の公開クライアント
 .SH 形式
 .LP
 .nf
-/usr/bin/pkgsend [\fIoptions\fR] \fIcommand\fR [\fIcmd_options\fR] [\fIoperands\fR]
+/usr/bin/pkgsend [\fIoptions\fR] \fIcommand \fR [\fIcmd_options\fR] [\fIoperands\fR] 
 .fi
 
 .LP
 .nf
-/usr/bin/pkgsend generate [-T \fIpattern\fR] [--target \fIfile\fR]
-    \fIsource\fR ...
+/usr/bin/pkgsend generate [-T \fIpattern\fR] [--target \fI file\fR] \fIsource\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkgsend publish [-b \fIbundle\fR ...] [-d \fIsource\fR ...] 
-    [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog]
-    [\fImanifest\fR ...]
+/usr/bin/pkgsend publish [-b \fIbundle\fR ...] [-d \fI source\fR ...] [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog] [\fImanifest\fR ...]
 .fi
 
 .SH 機能説明
 .sp
 .LP
 \fBpkgsend\fR では、パッケージのマニフェストを使用して、新しいパッケージと新しいパッケージのバージョンをイメージパッケージングリポジトリに公開できます。リポジトリを作成または管理するには、\fBpkgrepo\fR(1) を参照してください。既存のリポジトリ内でパッケージからパッケージアーカイブを作成するには、\fBpkgrecv\fR(1) を参照してください。パッケージのマニフェストの詳細は、\fBpkg\fR(5) を参照してください。
+.sp
+.LP
+\fBpkgsend\fR 操作後に、リポジトリに対して \fBpkgrepo refresh\fR または \fBpkgrepo rebuild\fR を実行し、検索インデックスを構築します。
 .SH オプション
 .sp
 .LP
-次のオプションを指定できます。
+サポートしているオプションは、次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR or \fB-?\fR\fR
+\fB\fB-?\fR\fR
 .ad
-.RS 16n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 使用方法に関するメッセージを表示します。
 .RE
 
 .SH サブコマンド
 .sp
 .LP
-次のサブコマンドがサポートされています。
+サポートされているサブコマンドは次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fBgenerate [\fB-T\fR \fIpattern\fR] [\fB--target\fR \fIfile\fR] \fIsource\fR ... \fR\fR
+\fB\fBpkgsend generate\fR [\fB-T\fR \fI pattern\fR] [\fB--target\fR \fIfile\fR] \fI source\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-各 \fIsource\fR (SVR4 パッケージ、ディレクトリ、\fBtar\fR ファイルなど) を読み取り、その \fIsource\fR を\fB標準出力\fRに表示するマニフェストを生成します。これで、出力されたマニフェストに注釈を加え、\fBpkgdepend\fR(1) を使用して依存関係を追加または分析し、\fBpkglint\fR(1) を使用してその正当性を検証してから \fBpublish\fR サブコマンドに渡すことができるようになります。サポートされているソースを次に示します。
+各 \fIsource\fR (SVR4 パッケージ、ディレクトリ、\fBtar\fR ファイルなど) を読み取り、その \fIsource\fR を\fB標準出力\fRに表示するマニフェストを生成します。出力マニフェストで、\fBfile\fR および \fBdir\fR アクションの所有者は \fBroot\fR に設定され、グループは \fBbin\fR に設定されています。
+.sp
+これで、出力されたマニフェストに注釈を加え、\fBpkgdepend\fR を使用して依存関係を追加または分析し、\fBpkglint\fR を使用してその正当性を検証してから \fBpublish\fR サブコマンドに渡すことができるようになります。
+.sp
+.LP
+サポートされているソースを次に示します。
 .RS +4
 .TP
 .ie t \(bu
@@ -83,9 +92,9 @@
 .ne 2
 .mk
 .na
-\fB\fB*\fR\fR
+\fB*\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 すべてと一致します。
 .RE
@@ -94,9 +103,9 @@
 .ne 2
 .mk
 .na
-\fB\fB?\fR\fR
+\fB?\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 任意の単一文字と一致します。
 .RE
@@ -105,9 +114,9 @@
 .ne 2
 .mk
 .na
-\fB\fB[\fIseq\fR]\fR\fR
+\fB[\fIseq\fR]\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 \fIseq\fR 内にある任意の文字と一致します。
 .RE
@@ -116,9 +125,9 @@
 .ne 2
 .mk
 .na
-\fB\fB![\fIseq\fR]\fR\fR
+\fB![\fIseq\fR]\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 \fIseq\fR 内にない文字と一致します。
 .RE
@@ -134,21 +143,58 @@
 .ne 2
 .mk
 .na
-\fB\fBpublish [\fB-b\fR \fIbundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fI repo_uri_or_path\fR] [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR\fR
+\fB\fBpkgsend publish\fR [\fB-b\fR \fI bundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB-T\fR \fI pattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...] \fR
 .ad
 .sp .6
 .RS 4n
 指定されたパッケージマニフェストを使用するパッケージをターゲットパッケージリポジトリに公開します。これにより、指定されたソースからそのパッケージ用のファイルが取得されます。複数のマニフェストが指定されている場合、それらのマニフェストは指定された順序で追加されます。マニフェストが指定されていない場合、\fBstdin\fR からマニフェストが読み取られます。
 .sp
-\fB-b\fR を指定すると、マニフェスト内でファイルを検索するときに、指定されたバンドルが、検索するソースの一覧に追加されます。バンドルは、tar ファイルや SVR4 パッケージなどのソースです。このオプションが複数回指定されている場合、ソースはコマンド行に表示される順序で検索されます。\fB-b\fR と \fB-d\fR の両方が指定されている場合、\fB-d\fR のソースが最初に検索されます。サポートされているバンドルとその使用方法の詳細は、上記の \fBgenerate\fR サブコマンドを参照してください。
+指定しない場合、\fBpkgsend publish\fR はビルドバージョンをパッケージ FMRI に追加します。\fBpublish\fR ツールは、タイムスタンプも (UTC の現在時間) をパッケージ FMRI に追加します。パッケージ FMRI のバージョン文字列については、\fBpkg \fR(5) のマニュアルページを参照してください。
 .sp
-\fB-b\fR を指定すると、マニフェスト内でファイルを検索するときに、指定されたディレクトリが、検索するソースの一覧に追加されます。このオプションが複数回指定されている場合、ソースはコマンド行に表示される順序で検索されます。サポートされているソースとその使用方法の詳細は、上記の \fBgenerate\fR サブコマンドを参照してください。
+.ne 2
+.mk
+.na
+\fB\fB-b\fR \fIbundle\fR\fR
+.ad
+.sp .6
+.RS 4n
+マニフェスト内でファイルを検索するときに、指定されたバンドルを検索するソースの一覧に追加します。バンドルは、tar ファイルや SVR4 パッケージなどのソースです。このオプションが複数回指定されている場合、ソースはコマンド行に表示される順序で検索されます。\fB-b\fR と \fB-d\fR の両方が指定されている場合、\fB-d\fR のソースが最初に検索されます。サポートされているバンドルとその使用方法の詳細は、前述の \fBgenerate\fR サブコマンドを参照してください。
+.RE
+
 .sp
-\fB-s\fR を指定すると、特定の URI またはファイルシステムパスに存在しているリポジトリにパッケージが公開されます。公開についての制限事項と推奨事項の詳細は、次の「注意事項」の節を参照してください。また、「環境変数」の節も参照してください。
+.ne 2
+.mk
+.na
+\fB\fB-d\fR \fIsource\fR\fR
+.ad
+.sp .6
+.RS 4n
+マニフェスト内でファイルを検索するときに、指定されたディレクトリを検索するソースの一覧に追加します。このオプションが複数回指定されている場合、ソースはコマンド行に表示される順序で検索されます。サポートされているソースとその使用方法の詳細は、上記の \fBgenerate\fR サブコマンドを参照してください。
+.RE
+
 .sp
-\fB--no-catalog\fR を指定すると、パブリッシャーのカタログにパッケージが追加されなくなります。パブリッシャーのカタログの更新は連続で実行されるため、複数のパッケージを一度に公開する場合には常にこのオプションを使用することを推奨します。公開が完了すると、\fBpkgrepo\fR(1) の \fBrefresh\fR サブコマンドを使用して、新しいパッケージを各パブリッシャーのカタログに追加できます。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+特定の URI またはファイルシステムパスに存在しているリポジトリにパッケージが公開されます。公開についての制限事項と推奨事項の詳細は、次の「注意事項」のセクションを参照してください。また、「環境変数」のセクションも参照してください。
+.RE
+
 .sp
-その他のすべてのオプションの使用法と効果については、上記の \fBgenerate\fR サブコマンドを参照してください。
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
+.ad
+.sp .6
+.RS 4n
+パッケージを発行元のカタログに追加しません。パブリッシャーのカタログの更新は連続で実行されるため、複数のパッケージを一度に公開する場合には常にこのオプションを使用することを推奨します。公開が完了すると、\fBpkgrepo\fR の \fBrefresh\fR サブコマンドを使用して、新しいパッケージを各発行元のカタログに追加できます。
+.RE
+
+\fB-T\fR オプションの説明については、前述の \fBgenerate \fR サブコマンドを参照してください。
 .RE
 
 .SH 環境
@@ -256,7 +302,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -283,7 +329,7 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
@@ -323,7 +369,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkgdepend\fR(1), \fBpkgrepo\fR(1), \fBpkg.depotd \fR(1M), \fBpkg\fR(5)
+\fBpkgdepend\fR(1)、\fBpkgrepo\fR(1)、\fBpkg.depotd\fR(1M)、\fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pkgsign.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pkgsign.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgsign 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgsign 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pkgsign \- Image Packaging System の署名ユーティリティー
 .SH 形式
@@ -21,34 +21,106 @@
 .SH オプション
 .sp
 .LP
-次のオプションを指定できます。
+サポートしているオプションは、次のとおりです。
 .sp
-.LP
-\fB-a\fR を指定すると、デフォルトの署名アルゴリズムではなく、\fIhash_algorithm\fR 署名アルゴリズムが使用されます。デフォルトの署名アルゴリズムは \fBrsa-sha256\fR です。サポートされている署名アルゴリズムは、\fBrsa-sha256\fR、\fBrsa-sha384\fR、\fBrsa-sha512\fR、\fBsha256\fR、\fBsha384\fR、\fBsha512\fR です。ハッシュアルゴリズムを指定するだけの署名アルゴリズムを使用すると、署名の値は、パッケージのマニフェストのハッシュになります。\fBrsa\fR とハッシュアルゴリズムを指定する署名アルゴリズムを使用すると、署名の値は、提供された非公開鍵で署名が追加されたマニフェストのハッシュになります (\fB-c\fR オプションと \fB-k\fR オプションを参照)。
+.ne 2
+.mk
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用方法に関するメッセージを表示します。
+.RE
+
 .sp
-.LP
-\fB-c\fR を指定すると、証明書 \fIpath_to_signing_certificate\fR が、このアクションで署名の値を検証するときに使用する証明書として追加されます。\fB-c\fR オプションは、\fB-k\fR オプションでのみ使用されます。
+.ne 2
+.mk
+.na
+\fB\fB-a\fR \fIhash_algorithm\fR\fR
+.ad
+.sp .6
+.RS 4n
+デフォルトの署名アルゴリズムではなく、\fIhash_algorithm\fR 署名アルゴリズムが使用されます。デフォルトの署名アルゴリズムは \fBrsa-sha256\fR です。サポートされている署名アルゴリズムは、\fBrsa-sha256\fR、\fBrsa-sha384\fR、\fBrsa-sha512\fR、\fBsha256\fR、\fBsha384\fR、\fBsha512\fR です。ハッシュアルゴリズムを指定するだけの署名アルゴリズムを使用すると、署名の値は、パッケージのマニフェストのハッシュになります。\fBrsa\fR とハッシュアルゴリズムを指定する署名アルゴリズムを使用すると、署名の値は、提供された非公開鍵で署名が追加されたマニフェストのハッシュになります (\fB-c\fR オプションと \fB-k\fR オプションを参照)。
+.RE
+
 .sp
-.LP
-\fB-i\fR を指定すると、証明書 \fIpath_to_intermediate_cert\fR が、\fB-c\fR への引数として指定された証明書 \fIpath_to_signing_certificate\fR を検証するときに使用する証明書として追加されます。複数の証明書を追加するには、\fB-i\fR を複数回指定します。
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIpath_to_signing_certificate\fR\fR
+.ad
+.sp .6
+.RS 4n
+証明書 \fIpath_to_signing_certificate\fR を、このアクションで署名の値を検証するときに使用する証明書として追加します。\fB-c\fR オプションは、\fB-k\fR オプションでのみ使用されます。
+.RE
+
 .sp
-.LP
-\fB-k\fR を指定すると、\fIpath_to_private_key\fR に格納された非公開鍵を使用してマニフェストに署名が追加されます。\fB-k\fR オプションは、\fB-c\fR オプションでのみ使用されます。\fB-k\fR が設定されていない場合、署名の値はマニフェストのハッシュになります。
+.ne 2
+.mk
+.na
+\fB\fB-i\fR \fIpath_to_intermediate_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+証明書 \fIpath_to_intermediate_cert\fR を、\fB-c\fR への引数として指定された証明書 \fIpath_to_signing_certificate\fR を検証するときに使用する証明書として追加します。複数の証明書を追加するには、\fB-i\fR を複数回指定します。
+.RE
+
 .sp
-.LP
-\fB-n\fR を指定すると、評価実行が行われ、リポジトリは一切変更されません。
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIpath_to_private_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fIpath_to_private_key\fR に格納された非公開鍵を使用してマニフェストに署名を追加します。\fB-k\fR オプションは、\fB-c\fR オプションでのみ使用されます。\fB-k\fR が設定されていない場合、署名の値はマニフェストのハッシュになります。
+.RE
+
 .sp
-.LP
-\fB-s\fR を指定すると、\fIpath_or_uri\fR にあるリポジトリ内のパッケージに署名が追加されます。
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+評価実行を行い、リポジトリは一切変更しません。
+.RE
+
 .sp
-.LP
-\fB--help\fR を指定すると、使用法のメッセージが表示されます。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+\fIpath_or_uri\fR にあるリポジトリ内のパッケージに署名を追加します。
+.RE
+
 .sp
-.LP
-\fB--no-index\fR を指定すると、署名付きマニフェストが再公開されたあとに、リポジトリの検索インデックスが更新されません。
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+署名付きマニフェストが再公開されたあとに、リポジトリの検索インデックスを更新しません。
+.RE
+
 .sp
-.LP
-\fB--no-catalog\fR を指定すると、署名付きマニフェストが再公開されたあとに、リポジトリのカタログが更新されません。
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
+.ad
+.sp .6
+.RS 4n
+署名付きマニフェストが再公開されたあとに、リポジトリのカタログを更新しません。
+.RE
+
 .SH 使用例
 .LP
 \fB例 1 \fRマニフェストのハッシュ値を使用した署名の追加
@@ -84,7 +156,7 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
@@ -111,7 +183,7 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
 .RS 6n
 .rt  
@@ -162,7 +234,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpkg\fR(1), \fBpkgrecv\fR(1), \fBpkgsend\fR(1), \fBpkgrepo\fR(1M), \fBpkg\fR(5)
+\fBpkg\fR(1), \fBpkgrecv\fR(1), \fBpkgsend\fR(1), \fBpkgrepo\fR(1), \fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/ja_JP/pm-updatemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/ja_JP/pm-updatemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pm-updatemanager 1 "2011 年 7 月 28 日" "SunOS 5.11" "ユーザーコマンド"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pm-updatemanager 1 "2012 年 5 月 27 日" "SunOS 5.11" "ユーザーコマンド"
 .SH 名前
 pm-updatemanager \- パッケージを更新するためのアプリケーション
 .SH 形式
@@ -11,8 +11,8 @@
 
 .LP
 .nf
-/usr/bin/pm-updatemanager [-hdR] [--help] [--debug]
-    [--image-dir \fIdir\fR]
+/usr/bin/pm-updatemanager [-h | --help] [-d | --debug]
+    [-R \fIdir\fR | --image-dir \fIdir\fR]
 .fi
 
 .SH 機能説明
@@ -28,15 +28,19 @@
 .SH オプション
 .sp
 .LP
-次のオプションを指定できます。
+サポートしているオプションは、次のとおりです。
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-h\fR or \fB--help\fR\fR
+\fB\fB-h\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 使用方法に関するメッセージを表示します。
 .RE
 
@@ -44,10 +48,14 @@
 .ne 2
 .mk
 .na
-\fB\fB-d\fR or \fB--debug\fR\fR
+\fB\fB-d\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--debug\fR\fR
+.ad
+.sp .6
+.RS 4n
 デバッグモードで \fBpm-updatemanager\fR を実行します。
 .RE
 
@@ -55,10 +63,14 @@
 .ne 2
 .mk
 .na
-\fB\fB-R\fR or \fB--image-dir\fR \fI dir\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
 自動的に検出されたイメージではなく、\fIdir\fR をルートとするイメージに対して処理を行います。
 .RE
 
@@ -98,14 +110,14 @@
 .SH 終了ステータス
 .sp
 .LP
-次の終了値が返されます。
+次の終了ステータスが返されます。
 .sp
 .ne 2
 .mk
 .na
 \fB\fB0\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
 すべてが動作しました。
 .RE
@@ -116,7 +128,7 @@
 .na
 \fB\fB1\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
 エラーが発生した。
 .RE
@@ -125,9 +137,9 @@
 .ne 2
 .mk
 .na
-\fB\fB2\fR \fR
+\fB\fB2\fR\fR
 .ad
-.RS 6n
+.RS 5n
 .rt  
 無効なコマンド行オプションが指定された。
 .RE
@@ -154,7 +166,7 @@
 .SH 関連項目
 .sp
 .LP
-\fBpackagemanager\fR(1), \fBpkg\fR(1), \fBpkg \fR(5)
+\fBpackagemanager\fR(1), \fBpkg\fR(1), \fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/packagemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/packagemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH packagemanager 1 "21 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH packagemanager 1 "27 May 2012" "SunOS 5.11" "User Commands"
 .SH NAME
 packagemanager \- GUI for the Image Packaging System
 .SH SYNOPSIS
@@ -282,7 +281,7 @@
 Package Manager online help
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
 .SH NOTES
 .sp
 .LP
--- a/src/man/pkg.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkg.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkg 1 "22 Apr 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkg 1 "19 Apr 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkg \- Image Packaging System retrieval client
 .SH SYNOPSIS
@@ -46,13 +45,13 @@
 
 .LP
 .nf
-/usr/bin/pkg list [-Hafnsuv] [-g \fIpath_or_uri\fR]...
+/usr/bin/pkg list [-Hafnqsuv] [-g \fIpath_or_uri\fR]...
     [--no-refresh] [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg info [-lr] [-g \fIpath_or_uri\fR]... [--license]
+/usr/bin/pkg info [-lqr] [-g \fIpath_or_uri\fR]... [--license]
     [\fIpkg_fmri_pattern\fR ...]
 .fi
 
@@ -116,7 +115,7 @@
 
 .LP
 .nf
-/usr/bin/pkg variant [-H] [variant.\fIvariant_pattern\fR ...]
+/usr/bin/pkg variant [-Haiv] [-F \fIformat\fR] [\fIvariant_pattern\fR ...]
 .fi
 
 .LP
@@ -131,7 +130,7 @@
 
 .LP
 .nf
-/usr/bin/pkg facet [-H] [\fIfacet_pattern\fR ...]
+/usr/bin/pkg facet [-Haim] [-F \fIformat\fR] [\fIfacet_pattern\fR ...]
 .fi
 
 .LP
@@ -210,7 +209,7 @@
     [--set-property \fIname_of_property\fR=\fIvalue\fR]
     [--add-property-value \fIname_of_property\fR=\fIvalue_to_add\fR]
     [--remove-property-value \fIname_of_property\fR=\fIvalue_to_remove\fR]
-    [--unset-property \fIname_of_property_to_delete\fR]
+    [--unset-property \fIname_of_property_to_delete\fR] 
     [--proxy \fIproxy_to_use\fR] \fIpublisher\fR
 .fi
 
@@ -650,7 +649,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkg list\fR [\fB-Hafnsuv\fR] [\fB-g\fR \fIpath_or_uri\fR]... [\fB--no-refresh\fR] [\fIpkg_fmri_pattern\fR ...]\fR
+\fB\fBpkg list\fR [\fB-Hafnqsuv\fR] [\fB-g\fR \fIpath_or_uri\fR]... [\fB--no-refresh\fR] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -716,7 +715,7 @@
 .ad
 .sp .6
 .RS 4n
-List installed packages and list the newest version of packages that are not installed but could be installed in this image. Packages can be installed if they are allowed by the installed incorporations and by the image's variants. If one or more patterns are specified, then the newest version matching the specified pattern and allowed by any installed incorporations and the image's variants is listed. Without \fB-a\fR, list only installed packages.
+List installed packages and the newest version of packages that are available for installation. Packages are considered to be available for installation if they are allowed by the installed incorporations and by the image's variants. If one or more patterns are specified, then the newest version matching the specified pattern and allowed by any installed incorporations and the image's variants is listed. Without \fB-a\fR, list only installed packages.
 .RE
 
 .sp
@@ -756,6 +755,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+Do not list any packages, but return failure if there are any fatal errors.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-s\fR\fR
 .ad
 .sp .6
@@ -771,7 +781,7 @@
 .ad
 .sp .6
 .RS 4n
-List installed packages that have newer versions available. This option cannot be used with \fB-g\fR.
+List only packages with newer versions available. This option cannot be used with \fB-g\fR.
 .RE
 
 .sp
@@ -844,6 +854,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+Do not display any package information, but return failure if there are any fatal errors.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-r\fR\fR
 .ad
 .sp .6
@@ -859,7 +880,7 @@
 .ad
 .sp .6
 .RS 4n
-Display the license texts for the packages. This option can be combined with \fB-l\fR, \fB-q\fR, or \fB-r\fR. Return success if all \fIpkg_fmri_pattern\fR patterns match known packages and have licenses. Return failure if one or more patterns are unmatched or match packages that do not have licenses.
+Display the license texts for the packages. This option can be combined with \fB-l\fR, \fB-q\f, or R\fB-r\fR. When all patterns match a known package and have licenses, the command will return success. If one or more patterns are unmatched or match packages that do not have licenses, the command will return failure.
 .RE
 
 .RE
@@ -1326,7 +1347,7 @@
 .ad
 .sp .6
 .RS 4n
-Suppress progress messages and all other output during the requested operation.
+Print nothing, but return failure if there are any fatal errors.
 .RE
 
 .sp
@@ -1409,7 +1430,7 @@
 .ad
 .sp .6
 .RS 4n
-Revert all files tagged with \fItag-name\fR.
+Revert all files tagged with \fItag-name\fR, and remove any unpackaged files or directories that are under directories with this tag and that match \fIpattern\fR. See the description of the \fBrevert-tag\fR attribute in "File Actions" and "Directory Actions" in the \fBpkg\fR(5) man page for more information about \fItag-name\fR and \fIpattern\fR.
 .RE
 
 .sp
@@ -1555,7 +1576,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkg variant\fR [\fB-H\fR] [variant.\fIvariant_pattern\fR ...]\fR
+\fB\fBpkg variant\fR [\fB-Haiv\fR] [\fB-F\fR \fIformat\fR] [\fIvariant_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -1575,6 +1596,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-F\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify an alternative output format. Currently, only \fBtsv\fR (Tab Separated Values) is valid.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-H\fR\fR
 .ad
 .sp .6
@@ -1582,6 +1614,39 @@
 Omit the headers from the listing.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display all variants explicitly set in the image and all variants that are listed in installed packages. This option cannot be combined with \fB-i\fR.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-i\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display all variants that are listed in installed packages. This option cannot be combined with \fB-a\fR.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display the possible variant values that can be set for installed packages. This option can be combined with \fB-a\fR and \fB-i\fR.
+.RE
+
 .RE
 
 .sp
@@ -1603,11 +1668,11 @@
 .ne 2
 .mk
 .na
-\fB\fBpkg facet\fR [\fB-H\fR] [\fIfacet_pattern\fR ...]\fR
+\fB\fBpkg facet\fR [\fB-Haim\fR] [\fB-F\fR \fIformat\fR] [\fIfacet_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-Display the current values of all facets that have been explicitly set in this image by using the \fBpkg change-facet\fR command. See "Facets and Variants" in the \fBpkg\fR(5) man page for more information about facets.
+Display the current values and source of all facets that have been explicitly set in this image by using the \fBpkg change-facet\fR command or inherited from a parent image. See "Facets and Variants" in the \fBpkg\fR(5) man page for more information about facets.
 .sp
 .ne 2
 .mk
@@ -1623,6 +1688,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-F\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify an alternative output format. Currently, only \fBtsv\fR (Tab Separated Values) is valid.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-H\fR\fR
 .ad
 .sp .6
@@ -1630,6 +1706,39 @@
 Omit the headers from the listing.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display all facets explicitly set in the image and all facets that are listed in installed packages. This option cannot be combined with \fB-i\fR.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-i\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display all facets that are listed in installed packages. This option cannot be combined with \fB-a\fR.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
+.ad
+.sp .6
+.RS 4n
+Include masked facets in the output. Include a column indicating which (if any) facets are masked.
+.RE
+
 .RE
 
 .sp
@@ -1877,17 +1986,6 @@
 .ne 2
 .mk
 .na
-\fB\fB-F\fR\fR
-.ad
-.sp .6
-.RS 4n
-Specify an alternative output format. Currently, only \fBtsv\fR (Tab Separated Values) is valid.
-.RE
-
-.sp
-.ne 2
-.mk
-.na
 \fB\fB-H\fR\fR
 .ad
 .sp .6
@@ -1917,6 +2015,17 @@
 Display only enabled publishers.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify an alternative output format. Currently, only \fBtsv\fR (Tab Separated Values) is valid.
+.RE
+
 .RE
 
 .sp
@@ -1995,7 +2104,7 @@
 .ad
 .sp .6
 .RS 4n
-For verifying signed packages, add the specified certificate as a CA certificate that is trusted. The hashes of the PEM representation of the user-approved CA certificates are listed in the detailed output of the \fBpkg publisher\fR command.
+Add the specified certificate as a CA certificate that is trusted. The hashes of the PEM representation of the user-approved CA certificates are listed in the detailed output of the \fBpkg publisher\fR command.
 .RE
 
 .sp
@@ -2006,7 +2115,7 @@
 .ad
 .sp .6
 .RS 4n
-For verifying signed packages, treat the certificate with the given hash of its PEM representation as revoked. The hashes of the user-revoked CA certificates are listed in the detailed output of the \fBpkg publisher\fR command.
+Treat the certificate with the given hash of its PEM representation as revoked. The hashes of the user-revoked CA certificates are listed in the detailed output of the \fBpkg publisher\fR command.
 .RE
 
 .sp
@@ -2017,7 +2126,7 @@
 .ad
 .sp .6
 .RS 4n
-For verifying signed packages, remove the certificate with the given hash from the list of approved certificates and the list of revoked certificates.
+Remove the certificate with the given hash from the list of approved certificates and the list of revoked certificates.
 .RE
 
 .sp
@@ -3476,7 +3585,7 @@
 .ad
 .sp .6
 .RS 4n
-Seconds below the \fBlowspeed\fR limit (1024 bytes/second) during transport operations before the client aborts the operation. A value of 0 means do not abort the operation.
+Seconds below the \fBlowspeed\fR limit (1024 bytes/sec) during transport operations before the client aborts the operation. A value of 0 means do not abort the operation.
 .sp
 Default value: 30
 .RE
@@ -3728,7 +3837,7 @@
 \fBpkgsend\fR(1), \fBpkg.depotd\fR(1M), \fBglob\fR(3C), \fBpkg\fR(5), \fBbeadm\fR(1M)
 .sp
 .LP
-\fIAdding and Updating Oracle Solaris 11.2 Software Packages\fR
+\fIAdding and Updating Oracle Solaris 11.1 Software Packages\fR
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkg.5	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkg.5	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2009, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkg 5 "04 Apr 2013" "SunOS 5.11" "Standards, Environments, and Macros"
+.\" Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkg 5 "1 Mar 2013" "SunOS 5.11" "Standards, Environments, and Macros"
 .SH NAME
 pkg \- Image Packaging System
 .SH DESCRIPTION
@@ -132,7 +131,7 @@
 The payload is a positional attribute in that it is not named. It is the first word after the action name. In a published manifest, it is the \fBSHA-1\fR hash of the file contents. If present in a manifest that has yet to be published, it represents the path where the payload can be found. See \fBpkgsend\fR(1). The hash attribute can be used instead of the positional attribute, should the value include an equals sign. Both can be used in the same action. However, the hashes must be identical.
 .sp
 .LP
-The \fBpreserve\fR and \fBoverlay\fR attributes affect whether and how a \fBfile\fR action is installed.
+Other attributes include:
 .sp
 .ne 2
 .mk
@@ -141,101 +140,15 @@
 .ad
 .sp .6
 .RS 4n
-Specifies when and how files are preserved during package operations.
-.sp
-When a package is initially installed, if a file delivered by the package has a \fBpreserve\fR attribute defined with any value and the file already exists in the image, the existing file is stored in \fB/var/pkg/lost+found\fR and the packaged file is installed.
+This specifies that the file's contents should not be overwritten on upgrade if the contents are determined to have changed since the file was installed or last upgraded. On initial installs, if an existing file is found, the file is salvaged (stored in \fB/var/pkg/lost+found\fR).
 .sp
-When a package is initially installed, if a file delivered by the package has a \fBpreserve\fR attribute defined and the file does not already exist in the image, whether that file is installed depends on the value of the \fBpreserve\fR attribute:
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the value of \fBpreserve\fR is \fBlegacy\fR, the packaged file is not installed.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the value of \fBpreserve\fR is not \fBlegacy\fR, the packaged file is installed.
-.RE
-When a package is downgraded, if a file delivered by the downgraded version of the package has a \fBpreserve\fR attribute defined with any value and all of the following conditions are true, the file that currently exists in the image is renamed with the extension \fB\&.update\fR, and the file from the downgraded package is installed.
-.RS +4
-.TP
-.ie t \(bu
-.el o
-The file exists in the image.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-The content of the file delivered by the downgraded version of the package is different from the content of the file delivered by the currently installed version of the package.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-The content of the file delivered by the downgraded version of the package is different from the content of the file that exists in the image.
-.RE
-If any of the above conditions is not true, the file is treated the same as if the package is being upgraded, rather than downgraded.
-.sp
-When a package is upgraded, if a \fBfile\fR action delivered by the upgraded version of the package has a \fBpreserve\fR attribute defined with any value and the \fBfile\fR action is the same as the \fBfile\fR action delivered by the currently installed version of the package, the file is not installed, and the file that exists in the image is not modified. Any modifications made since the previous version was installed are preserved.
+If the value of \fBpreserve\fR is \fBrenameold\fR, then the existing file is renamed with the extension \fB\&.old\fR, and the new file is put in its place.
 .sp
-When a package is upgraded, if a \fBfile\fR action delivered by the upgraded version of the package has a \fBpreserve\fR attribute defined and the \fBfile\fR action is new or is different from the \fBfile\fR action delivered by the currently installed version of the package, the upgrade is done in the following way:
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file does not exist in the image, the new file is installed.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package exists in the image, did not exist in the currently installed version of the package, and was not renamed or moved by using the \fBoriginal_name\fR attribute (see below), then the existing file is stored in \fB/var/pkg/lost+found\fR and the file delivered by the upgraded version of the package is installed.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package exists in the image and has different content from the file delivered by the currently installed version of the package, the upgrade is done according to the value of the \fBpreserve\fR attribute:
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package has a \fBpreserve\fR value of \fBrenameold\fR, the existing file is renamed with the extension \fB\&.old\fR, and the new file is installed with updated permissions and timestamp (if present). See the \fBtimestamp\fR attribute description below.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package has a \fBpreserve\fR value of \fBrenamenew\fR, the new file is installed with the extension \fB\&.new\fR and the existing file is not modified.
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package has a \fBpreserve\fR value of \fBtrue\fR, the new file is not installed, but the permissions and timestamp (if present) are reset on the existing file.
-.RE
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package exists in the image, has the same content as the file delivered by the currently installed version of the package, and has a \fBpreserve\fR value of either \fBrenameold\fR or \fBrenamenew\fR, the existing file is replaced by the file delivered by the upgraded version of the package, including replacing permissions and timestamp (if present).
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package exists in the image, has a \fBpreserve\fR value of \fBlegacy\fR in the upgraded package, and has a different \fBpreserve\fR value in the currently installed version of the package, the existing file is renamed with the extension \fB\&.legacy\fR, and the new file is installed with updated permissions and timestamp (if present).
-.RE
-.RS +4
-.TP
-.ie t \(bu
-.el o
-If the file delivered by the upgraded version of the package exists in the image and has a \fBpreserve\fR value of \fBlegacy\fR in both the upgraded package and the currently installed version of the package, the permissions and timestamp (if present) are reset on the existing file.
-.RE
+If the value of \fBpreserve\fR is \fBrenamenew\fR, then the existing file is left alone, and the new file is installed with the extension \fB\&.new\fR.
+.sp
+If the value of \fBpreserve\fR is \fBlegacy\fR, then this file is not installed for initial package installs. On upgrades, any existing file is renamed with the extension \fB\&.legacy\fR, and then the new file is put in its place.
+.sp
+If the value of \fBpreserve\fR is \fBtrue\fR (or a value not listed above, such as \fBstrawberry\fR), then the existing file is left alone, and the new file is not installed.
 .RE
 
 .sp
@@ -246,39 +159,18 @@
 .ad
 .sp .6
 .RS 4n
-Specifies whether the action allows other packages to deliver a file at the same location or whether it delivers a file intended to overlay another file. This functionality is intended for use with configuration files that do not participate in any self-assembly (for example, \fB/etc/motd\fR) and that can be safely overwritten.
+This specifies whether the action allows other packages to deliver a file at the same location or whether it delivers a file intended to overlay another. This functionality is intended for use with configuration files that do not participate in any self-assembly (for example, \fB/etc/motd\fR) and that can be safely overwritten.
 .sp
 If \fBoverlay\fR is not specified, multiple packages cannot deliver files to the same location.
 .sp
-The \fBoverlay\fR attribute can have one of the following values:
+If the value of \fBoverlay\fR is \fBallow\fR, one other package is allowed to deliver a file to the same location. This value has no effect unless the \fBpreserve\fR attribute is also set.
 .sp
-.ne 2
-.mk
-.na
-\fB\fBallow\fR\fR
-.ad
-.RS 9n
-.rt  
-One other package is allowed to deliver a file to the same location. This value has no effect unless the \fBpreserve\fR attribute is also set.
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fBtrue\fR\fR
-.ad
-.RS 9n
-.rt  
-The file delivered by the action overwrites any other action that has specified \fBallow\fR.
-.RE
-
-Changes to the installed file are preserved based on the value of the \fBpreserve\fR attribute of the overlaying file. On removal, the contents of the file are preserved if the action being overlaid is still installed, regardless of whether the \fBpreserve\fR attribute was specified. Only one action can overlay another, and the \fBmode\fR, \fBowner\fR, and \fBgroup\fR attributes must match.
+If the value of \fBoverlay\fR is \fBtrue\fR, the file delivered by the action overwrites any other action that has specified \fBallow\fR. Changes to the installed file are preserved based on the value of the \fBpreserve\fR attribute of the overlaying file. On removal, the contents of the file are preserved if the action being overlaid is still installed, regardless of whether the \fBpreserve\fR attribute was specified. Only one action can overlay another, and the \fBmode\fR, \fBowner\fR, and \fBgroup\fR attributes must match.
 .RE
 
 .sp
 .LP
-The following attributes are recognized for ELF files:
+Files can also be "tasted," and depending on the flavor, can have additional attributes. For ELF files, the following attributes are recognized:
 .sp
 .ne 2
 .mk
@@ -313,9 +205,6 @@
 .RE
 
 .sp
-.LP
-The following additional attributes are recognized for \fBfile\fR actions:
-.sp
 .ne 2
 .mk
 .na
@@ -346,34 +235,14 @@
 .sp .6
 .RS 4n
 This attribute is used to tag editable files that should be reverted as a set. The value of the \fBrevert-tag\fR attribute is a \fItagname\fR. Multiple \fBrevert-tag\fR attributes can be specified for a single \fBfile\fR action. The file reverts to its manifest-defined state when \fBpkg revert\fR is invoked with any of those tags specified. See the \fBpkg\fR(1) man page for information about the \fBpkg revert\fR command.
-.RE
-
 .sp
-.ne 2
-.mk
-.na
-\fB\fBtimestamp\fR\fR
-.ad
-.sp .6
-.RS 4n
-This attribute is used to set the access and modification time on the file. The \fBtimestamp\fR attribute value must be expressed in UTC in ISO-8601 format, omitting the colons and hyphens.
-.sp
-The \fBtimestamp\fR attribute is essential when packaging \fB\&.pyc\fR or \fB\&.pyo\fR files for Python. The related \fB\&.py\fR file for the \fB\&.pyc\fR or \fB\&.pyo\fR files must be marked with the timestamp embedded within those files, as shown in the following example:
-.sp
-.in +2
-.nf
-file path=usr/lib/python2.6/vendor-packages/pkg/__init__.pyc ...
-file path=usr/lib/python2.6/vendor-packages/pkg/__init__.py \e
-     timestamp=20130311T221521Z ...
-.fi
-.in -2
-
+The \fBrevert-tag\fR attribute can also be specified at the directory level. See "Directory Actions" below.
 .RE
 
 .SS "Directory Actions"
 .sp
 .LP
-The \fBdir\fR action is like the \fBfile\fR action in that it represents a file system object. The \fBdir\fR action represents a directory instead of an ordinary file. The \fBdir\fR action has the same \fBpath\fR, \fBmode\fR, \fBowner\fR, and \fBgroup\fR attributes that the \fBfile\fR action has, and \fBpath\fR is the key attribute.
+The \fBdir\fR action is like the \fBfile\fR action in that it represents a file system object. The \fBdir\fR action represents a directory instead of an ordinary file. The \fBdir\fR action has the same \fBpath\fR, \fBmode\fR, \fBowner\fR, and \fBgroup\fR attributes that the \fBfile\fR action has, and \fBpath\fR is the key attribute. The \fBdir\fR action also accepts the \fBrevert-tag\fR attribute, but the value of the attribute is different for \fBfile\fR and \fBdir\fR actions.
 .sp
 .LP
 Directories are reference counted in IPS. When the last package that either explicitly or implicitly references a directory no longer does so, that directory is removed. If that directory contains unpackaged file system objects, those items are moved into \fB$IMAGE_META/lost+found\fR. See the "Files" section for more information about \fB$IMAGE_META\fR.
@@ -381,6 +250,17 @@
 .ne 2
 .mk
 .na
+\fB\fBrevert-tag\fR\fR
+.ad
+.sp .6
+.RS 4n
+This attribute is used to identify unpackaged files that should be removed as a set. See "File Actions" above for a description of how to specify this attribute for \fBfile\fR actions. For directories, the value of the \fBrevert-tag\fR attribute is \fItagname\fR\fB=\fR\fIpattern\fR. Multiple \fBrevert-tag\fR attributes can be specified for a single \fBdir\fR action. When \fBpkg revert\fR is invoked with a matching \fItagname\fR, any unpackaged files or directories under this \fBdir\fR directory that match \fIpattern\fR (using shell globbing characters) are removed. See the \fBpkg\fR(1) man page for information about the \fBpkg revert\fR command.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBsalvage-from\fR\fR
 .ad
 .sp .6
@@ -667,7 +547,7 @@
 .ad
 .sp .6
 .RS 4n
-The dependency must, if present, be at the specified value or better on the image to be modified prior to installation. If the value of the \fBroot-image\fR attribute is \fBtrue\fR, the dependency must be present on the image rooted at / in order to install this package.
+The dependency must, if present, be at the specified value or better on the image to be modified prior to installation. If the value of the \fBroot-image\fR attribute is \fBtrue\fR, the dependency must be present on the image rooted at / in order to install this package.  If the fmri also starts with pkg:/feature/firmware/, the remainder of the name is treated as a command in /usr/lib/fwenum that evaluates the firmware dependency. See the package developer's guide for details.
 .RE
 
 .sp
@@ -1022,7 +902,7 @@
 The \fBuser\fR action defines a UNIX user as defined in \fB/etc/passwd\fR, \fB/etc/shadow\fR, \fB/etc/group\fR, and \fB/etc/ftpd/ftpusers\fR files. Entries are added to the appropriate files for users defined with this \fBuser\fR action.
 .sp
 .LP
-The \fBuser\fR action is intended to define a user for a daemon or other software to use. Do not use the \fBuser\fR action to define administrative or interactive accounts.
+The  \fBuser\fR action is intended to define a user for a daemon or other software to use. Do not use the \fBuser\fR action to define administrative or interactive accounts.
 .sp
 .LP
 The following attributes are recognized:
@@ -1320,6 +1200,9 @@
 Facets are treated as boolean values by package clients: Facets can be set only to \fBtrue\fR (enabled) or \fBfalse\fR (disabled) in the image. By default, all facets are considered to be set to \fBtrue\fR in the image.
 .sp
 .LP
+Facets can either be set locally within an image or inherited from a parent image. Inherited facets are evaluated before, and hence take priority over, any local facets. If the same exact facet is both inherited and set locally, the inherited facet value masks the local value. Facet changes made via \fBpkg change-facet\fR will only affect local facets.
+.sp
+.LP
 The value of a facet tag on an action can be set to \fBall\fR or \fBtrue\fR to control how clients filter faceted actions. All values other than \fBall\fR or \fBtrue\fR have undefined behavior. See below for a description of the conditions that must exist in the image to install an action that has facet tags.
 .sp
 .LP
@@ -1358,7 +1241,7 @@
 
 file group=sys mode=0644 overlay=allow owner=root \e
   path=etc/motd pkg.csize=68 pkg.size=48 preserve=true \e
-  variant.debug.osnet=false
+  variant.debug.osnet=false 
 .fi
 .in -2
 
@@ -1517,16 +1400,16 @@
 .SH SEE ALSO
 .sp
 .LP
-\fBpkg\fR(1), \fBpkg\fR(1), \fBpkg\fR(1M), \fBpkg\fR(1M), \fBsvcs\fR(1), \fBsvcadm\fR(1M)
+\fBpkg\fR(1), \fBpkgsend\fR(1), \fBpkg.depotd\fR(1M), \fBpkg.sysrepo\fR(1M), \fBsvcs\fR(1), \fBsvcadm\fR(1M)
 .sp
 .LP
-\fIAdding and Updating Oracle Solaris 11.2 Software Packages\fR
+\fIAdding and Updating Oracle Solaris 11.1 Software Packages\fR
 .sp
 .LP
-\fICopying and Creating Oracle Solaris 11.2 Package Repositories\fR
+\fICopying and Creating Oracle Solaris 11.1 Package Repositories\fR
 .sp
 .LP
 \fIPackaging and Delivering Software With the Oracle Solaris 11 Image Packaging System\fR
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/man/pkg.depot-config.1m	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,333 @@
+'\" te
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkg.depotd-config 1M "14 Feb 2013" "SunOS 5.11" "System Administration Commands"
+.SH NAME
+pkg.depotd-config \- Image Packaging System HTTP depot configuration generator
+.SH SYNOPSIS
+.LP
+.nf
+/usr/lib/pkg.depot-config ( -d \fIrepository_dir\fR | -S )
+    -r \fIruntime_dir\fR [-c \fIcache_dir\fR] [-s \fIcache_size\fR] [-p \fIport\fR]
+    [-h \fIhostname\fR] [-l \fIlogs_dir\fR] [-T \fItemplate_dir\fR]
+    [-A] [-t \fIserver_type\fR] ( [-F] [-P \fIserver_prefix\fR] )
+.fi
+
+.SH DESCRIPTION
+.sp
+.LP
+\fBpkg.depotd-config\fR generates the configuration files for the Image Packaging System (IPS) depot. The IPS depot provides scalable read-only access to IPS package repositories over HTTP.
+.sp
+.LP
+The IPS depot is configured using the \fBsvc:/application/pkg/depot\fR Service Management Facility (SMF) service in conjunction with one or more instances of the \fBsvc:/application/pkg/server\fR service.
+.sp
+.LP
+\fBpkg.depot-config\fR generates a configuration for use by the \fBpkg/depot\fR service, or the \fBpkg.depot-config\fR command can be invoked on the command line to generate a standalone configuration.
+.sp
+.LP
+To change depot configuration, modify the properties of the \fBpkg/depot\fR service or the appropriate \fBpkg/server\fR service instance and refresh the instance. Modifying \fBpkg/server\fR service instance states can cause the \fBpkg/depot\fR service to be refreshed and the depot configuration files to be regenerated.
+.sp
+.LP
+To serve multiple repositories, you need a separate \fBpkg/server\fR service instance for each repository but only one \fBpkg/depot\fR service instance. Each instance of the \fBpkg/server\fR service provides a read/write depot server that supports HTTP and HTTPS for an individual repository. The \fBpkg/depot:default\fR service instance provides a scalable, read-only depot server that supports HTTP for multiple repositories.
+.sp
+.LP
+Each repository is supported by a \fBpkg/server\fR service instance. A repository might also be supported by the \fBpkg/depot:default\fR service. If the \fBpkg/standalone\fR property of a particular \fBpkg/server\fR instance is set to \fBtrue\fR, then the repository is served by the \fBpkg.depotd\fR process. If the \fBpkg/standalone\fR property of a particular \fBpkg/server\fR instance is set to \fBfalse\fR, then the repository is served by the \fBpkg/depot:default\fR service. Each \fBpkg/server\fR instance either runs \fBpkg.depotd\fR or contributes configuration information to \fBpkg/depot:default\fR.
+.sp
+.LP
+When you enable a \fBpkg/server\fR instance for which the \fBpkg/standalone\fR property set to \fBfalse\fR and the \fBpkg/readonly\fR property set to \fBtrue\fR, the \fBpkg/depot:default\fR configuration is refreshed, and that repository is served by the \fBpkg/depot:default\fR service. When you disable that same \fBpkg/server\fR instance, the \fBpkg/depot:default\fR service is refreshed, and that repository is no longer served by the \fBpkg/depot:default\fR service.
+.sp
+.LP
+You can configure the depot manually by using the \fBpkg.depot-config\fR command with the \fB-F\fR option. The \fB-F\fR option produces a web server configuration file that can be added to an existing web server. In this case, the depot runs with reduced functionality: \fBpkg\fR(1) search support and the depot browser user interface are not available. All other \fBpkg\fR(1) functionality required to install and update Oracle Solaris 11 systems is available.
+.sp
+.LP
+Use one of the following methods to pass repository paths and configuration to the depot server:
+.RS +4
+.TP
+.ie t \(bu
+.el o
+Use the \fBpkg.depot-config\fR command with the \fB-S\fR option. The \fB-S\fR option causes \fBpkg.depotd\fR to query the system for all instances of the \fBpkg/server\fR service that are marked as \fBonline\fR and have the \fBpkg/standalone\fR property set to \fBfalse\fR and the \fBpkg/readonly\fR property set to \fBtrue\fR.
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+Use the \fBpkg.depot-config\fR command with the \fB-d\fR option. The \fB-d\fR option provides a path to the \fBpkg\fR(5) repository to use. Multiple \fB-d\fR options are accepted.
+.RE
+.sp
+.LP
+Repositories must have file permissions that permit the files and directories in the repositories to be read by the \fBpkg5srv\fR user.
+.SH OPTIONS
+.sp
+.LP
+The following options are supported:
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-d\fR \fIprefix\fR=\fIrepository_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the path to a \fBpkg\fR(5) file repository to use. The \fIprefix\fR is used as a prefix into the \fBdepot-config\fR web server namespace where this repository can be accessed. The \fIrepository_dir\fR is a directory that contains a version 4 \fBpkg\fR(5) file repository, which is included in the depot server configuration. The \fB-d\fR option cannot be used with the \fB-S\fR option. At least one \fB-d\fR option is required if the \fB-S\fR option is not used. Multiple \fB-d\fR options are allowed.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-S\fR\fR
+.ad
+.sp .6
+.RS 4n
+Query the system for repositories to use. The \fB-S\fR option causes \fBpkg.depotd\fR to query the system for all instances of the \fBpkg/server\fR service that are marked as \fBonline\fR and have the \fBpkg/standalone\fR property set to \fBfalse\fR and the \fBpkg/readonly\fR property set to \fBtrue\fR. These property values allow the depot to run concurrently with \fBpkg/server\fR instances that do not have these properties set. See the \fBpkg.depotd\fR(1M) man page for information about \fBpkg.depotd\fR. The \fB-S\fR option cannot be used with the \fB-d\fR option.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR \fIruntime_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the default output directory for configuration files. This directory can also be specified by setting the \fBconfig/runtime_dir\fR property in the \fBpkg/server\fR service. When the \fBconfig/runtime_dir\fR property is used, the contents of this directory are recreated during service startup.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIcache_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the directory where the depot stores its cache. If the \fB-A\fR option is also used, the cache directory is also used to store server-side \fBpkg\fR(5) search indexes. This directory can also be specified by setting the \fBconfig/cache_dir\fR property in the \fBpkg/server\fR service.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIcache_size\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the maximum cache size for the depot. The \fIcache_size\fR value is an integer number of megabytes. If \fIcache_size\fR is 0, no caching is performed by the web server. The default value of \fIcache_size\fR is 0. If all file repositories served by the depot server are local to the depot server (not accessed over NFS), the default value of 0 is sufficient. This cache size can also be specified by setting the \fBconfig/cache_max\fR property in the \fBpkg/server\fR service.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIport\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the port number that the depot will listen to. The default value of \fIport\fR is 80. This port can also be specified by setting the \fBconfig/port\fR property in the \fBpkg/server\fR service.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-h\fR \fIhostname\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the host name to use as the argument to the Apache \fBServerName\fR directive. The default value of \fIhostname\fR is \fB0.0.0.0\fR. This host name can also be specified by setting the \fBconfig/host\fR property in the \fBpkg/server\fR service.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR \fIlogs_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the directory where the depot stores log files. The default value of \fIlogs_dir\fR is \fB/var/log/pkg/depot\fR. This directory can also be specified by setting the \fBconfig/log_dir\fR property in the \fBpkg/server\fR service.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-T\fR \fItemplate_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the directory where the depot builds the depot configuration and stores additional files needed to the run the depot. The default value of \fItemplate_dir\fR is \fB/etc/pkg/depot\fR. This directory can also be specified by setting the \fBconfig/template_dir\fR property in the \fBpkg/server\fR service. This directory should not need to be changed.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-A\fR \fR
+.ad
+.sp .6
+.RS 4n
+Refresh any search indices maintained by the depot when \fBpkgrepo refresh\fR is invoked. By default, search indices maintained by the depot are not refreshed when \fBpkgrepo refresh\fR is invoked. This option can also be specified by setting the \fBconfig/allow_refresh\fR property in the \fBpkg/server\fR service. Best practice is to not use the \fB-A\fR option or the \fBconfig/allow_refresh\fR property to refresh the index on production servers because the search index is refreshed automatically when the depot starts.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-t\fR \fIserver_type\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the type of web server that \fBpkg.depot-config\fR should output configuration information for. In this release, the value \fBapache2\fR is both the default value and the only accepted value for \fIserver_type\fR.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fR
+.ad
+.sp .6
+.RS 4n
+Produce a partial configuration that enables a web server to serve basic \fBpkg\fR(5) installation operations for clients using an existing web service. For an Apache web server running on the Oracle Solaris OS, the partial configuration file could be placed in \fB/etc/apache2/2.2/conf.d\fR. For other operating systems, consult your OS documentation to determine how to use this partial configuration file. See also the \fB-P\fR option.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR \fIserver_prefix\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the prefix used to map the depot into the web server namespace. The \fB-P\fR option is intended to be used with the \fB-F\fR option.
+.RE
+
+.SH PROVIDING ADDITIONAL SERVER CONFIGURATION
+.sp
+.LP
+When the \fB-F\fR option is not used, and the default \fB-t apache2\fR is set, the \fBsvc:/application/pkg/depot\fR service looks in \fB/etc/pkg/depot/conf.d\fR at startup for additional Apache configuration files that can be used to extend the server configuration. Consult the Apache web server documentation for details on the directives that are used to configure the web server.
+.SH EXAMPLES
+.LP
+\fBExample 1 \fRShowing How a Repository Is Served
+.sp
+.LP
+The system in this example is running multiple instances of \fBsvc:/application/pkg/server\fR and a single instance of \fBsvc:/application/pkg/depot\fR. The \fBpkg/server:standalone\fR instance has an associated \fBpkg.depotd\fR process. The \fBpkg.depotd\fR process serves the repository configured in the \fBpkg/server:standalone\fR service. The \fBpkg/server:userland\fR instance has no associated processes. The \fBpkg/depot:default\fR service serves the repository configured in the \fBpkg/server:userland\fR service.
+
+.sp
+.in +2
+.nf
+$ \fBsvcs pkg/server\fR
+STATE    STIME    FMRI
+disabled Feb_06   svc:/application/pkg/server:default
+online   Feb_03   svc:/application/pkg/server:userland
+online   Feb_03   svc:/application/pkg/server:standalone
+$ \fBsvcs pkg/depot\fR
+STATE    STIME    FMRI
+online   Feb_07   svc:/application/pkg/depot:default
+$ \fBsvcprop -p pkg/standalone -p pkg/readonly \e\fR
+\fBpkg/server:standalone\fR
+true
+true
+$ \fBsvcprop -p pkg/standalone -p pkg/readonly \e\fR
+\fBpkg/server:userland\fR
+false
+true
+$ \fBsvcs -p svc:/application/pkg/server:standalone\fR
+STATE    STIME    FMRI
+online   Feb_03   svc:/application/pkg/server:standalone
+         Jan_31       1206 pkg.depotd
+$ \fBsvcs -p svc:/application/pkg/server:userland\fR
+STATE    STIME    FMRI
+online   Feb_03   svc:/application/pkg/server:userland
+.fi
+.in -2
+.sp
+
+.LP
+\fBExample 2 \fRShowing Processes Associated With the Depot
+.sp
+.LP
+The following command shows \fBhttpd.worker\fR processes associated with the \fBpkg/depot\fR service.
+
+.sp
+.in +2
+.nf
+$ \fBsvcs -p pkg/depot\fR
+STATE    STIME    FMRI
+online   16:59:49 svc:/application/pkg/depot:default
+         16:59:48     6731 httpd.worker
+         16:59:48     6736 httpd.worker
+         16:59:48     6737 httpd.worker
+         16:59:48     6738 httpd.worker
+         17:00:05     6744 httpd.worker
+         17:05:59     6915 httpd.worker
+.fi
+.in -2
+.sp
+
+.SH EXIT STATUS
+.sp
+.LP
+The following exit values are returned:
+.sp
+.ne 2
+.mk
+.na
+\fB\fB0\fR\fR
+.ad
+.RS 13n
+.rt  
+Command succeeded.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB1\fR\fR
+.ad
+.RS 13n
+.rt  
+Command failed.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB2\fR\fR
+.ad
+.RS 13n
+.rt  
+Invalid command line options were specified.
+.RE
+
+.SH ATTRIBUTES
+.sp
+.LP
+See \fBattributes\fR(5) for descriptions of the following attributes:
+.sp
+
+.sp
+.TS
+tab() box;
+cw(2.75i) |cw(2.75i) 
+lw(2.75i) |lw(2.75i) 
+.
+ATTRIBUTE TYPEATTRIBUTE VALUE
+_
+Availability\fBpackage/pkg/depot\fR
+_
+Interface StabilityUncommitted
+.TE
+
+.SH SEE ALSO
+.sp
+.LP
+\fBsvcprop\fR(1), \fBsvcs\fR(1), \fBsvcadm\fR(1M), \fBsvccfg\fR(1M), \fBpkg.depotd\fR(1M), \fBpkg\fR(5)
+.sp
+.LP
+\fICopying and Creating Oracle Solaris 11.1 Package Repositories\fR
+.sp
+.LP
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkg.depotd.1m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkg.depotd.1m	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkg.depotd 1M "21 May 2013" "SunOS 5.11" "System Administration Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkg.depotd 1M "5 Jun 2012" "SunOS 5.11" "System Administration Commands"
 .SH NAME
 pkg.depotd \- Image Packaging System depot server
 .SH SYNOPSIS
@@ -791,7 +790,7 @@
 \fBdns-sd\fR(1M), \fBmdnsd\fR(1M), \fBpkg\fR(1), \fBpkgrepo\fR(1), \fBpkgsend\fR(1), \fBsyslogd\fR(1M), \fBsmf\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
 .SH NOTES
 .sp
 .LP
--- a/src/man/pkg.sysrepo.1m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkg.sysrepo.1m	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkg.sysrepo 1M "21 May 2013" "SunOS 5.11" "System Administration Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkg.sysrepo 1M "27 May 2012" "SunOS 5.11" "System Administration Commands"
 .SH NAME
 pkg.sysrepo \- Image Packaging System system repository configuration
 .SH SYNOPSIS
@@ -169,4 +168,4 @@
 \fBpkg\fR(1), \fBpkg.depotd\fR(1M), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgdepend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgdepend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgdepend 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgdepend \- Image Packaging System dependency analyzer
@@ -523,4 +522,4 @@
 \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgdiff.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgdiff.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgdiff 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgdiff \- compare package manifests
@@ -8,13 +7,14 @@
 .LP
 .nf
 /usr/bin/pkgdiff [-i \fIattribute\fR]... [-o \fIattribute\fR]
-    [-v \fIname\fR=\fIvalue\fR]... \fIfile1\fR \fIfile2\fR
+    [-t \fIaction_name\fR[,\fIaction_name\fR]...]...
+    [-v \fIname\fR=\fIvalue\fR]...  (\fIfile1\fR | -) (\fIfile2\fR | -)
 .fi
 
 .SH DESCRIPTION
 .sp
 .LP
-\fBpkgdiff\fR compares two package manifests and reports differences. \fBpkgdiff\fR sorts each manifest and action into a consistent order before comparison.
+\fBpkgdiff\fR compares two package manifests and reports differences. One of the manifests can be read from \fBstdin\fR by specifying \fB-\fR in place of the file name. \fBpkgdiff\fR sorts each manifest and action into a consistent order before comparison.
 .sp
 .LP
 Output is in the following form:
@@ -113,6 +113,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-t\fR \fIaction_name\fR[,\fIaction_name\fR]...\fR
+.ad
+.sp .6
+.RS 4n
+Only compare the specified actions. Multiple actions can be specified in a comma-separated list. The value of \fIaction_name\fR is one of the actions listed in "Actions" in the \fBpkg\fR(5) man page. For example, the following values could be specified for \fIaction_name\fR: \fBfile\fR, \fBdir\fR, \fBdriver\fR, \fBdepend\fR, \fBset\fR. This option can be specified multiple times.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-v\fR \fIname\fR=\fIvalue\fR\fR
 .ad
 .sp .6
@@ -204,4 +215,4 @@
 \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgfmt.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgfmt.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkgfmt 1 "21 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgfmt 1 "27 May 2012" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgfmt \- format a package manifest
 .SH SYNOPSIS
@@ -145,4 +144,4 @@
 \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkglint.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkglint.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,13 +1,12 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkglint 1 "02 Apr 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkglint 1 "27 May 2012" "SunOS 5.11" "User Commands"
 .SH NAME
 pkglint \- Image Packaging System package lint
 .SH SYNOPSIS
 .LP
 .nf
-/usr/bin/pkglint [-c \fIcache_dir\fR] [-r \fIrepo_uri\fR]... [-p \fIregexp\fR]
+/usr/bin/pkglint [-c \fIcache_dir\fR] [-r \fIrepo_uri\fR] [-p \fIregexp\fR]
     [-f \fIconfig_file\fR] [-b \fIbuild_no\fR] [-v]
     [-l \fIlint_uri\fR] | \fImanifest\fR ...
 .fi
@@ -141,7 +140,7 @@
 .ad
 .sp .6
 .RS 4n
-Specify a URI representing the location of the reference repository. If you specify \fB-r\fR, then you must also specify \fB-c\fR. The \fB-r\fR option can be specified multiple times.
+Specify a URI representing the location of the reference repository. If you specify \fB-r\fR, then you must also specify \fB-c\fR.
 .RE
 
 .sp
@@ -393,4 +392,4 @@
 \fBpkg\fR(1), \fBpkg.depotd\fR(1M), \fBpkgsend\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgmerge.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgmerge.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,13 +1,13 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkgmerge 1 "20 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkgmerge 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgmerge \- Image Packaging System package merging utility
 .SH SYNOPSIS
 .LP
 .nf
 /usr/bin/pkgmerge [-n] -d \fIdest_repo\fR
+    [-p \fIpublisher_prefix\fR]...
     -s \fIvariant\fR=\fIvalue\fR[,...],\fIsrc_repo\fR ...
     [\fIpkg_fmri_pattern\fR ...]
 .fi
@@ -22,9 +22,6 @@
 .sp
 .LP
 Non-identical actions that deliver to the same path in an input manifest result in \fBpkgmerge\fR exiting with an error.
-.sp
-.LP
-After a \fBpkgmerge\fR operation, if your destination repository must support \fBpkg search\fR operations, run \fBpkgrepo refresh\fR on the repository to update search indexes.
 .SH OPTIONS
 .sp
 .LP
@@ -70,6 +67,19 @@
 .ne 2
 .mk
 .na
+\fB\fB-p\fR \fIpublisher_prefix\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the name of the publisher from which to merge packages. This option can be specified multiple times.
+.sp
+By default, packages from all publishers in all source repositories are merged.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-s\fR \fIvariant\fR=\fIvalue\fR[,...],\fIsrc_repo\fR\fR
 .ad
 .sp .6
@@ -345,6 +355,22 @@
 .fi
 .in -2
 
+.LP
+\fBExample 5 \fRMerge Packages With Different Publisher Prefixes
+.sp
+.LP
+Merge only packages with the \fBdev\fR prefix, even though other packages in these repositories have the \fBexample.com\fR prefix.
+
+.sp
+.in +2
+.nf
+$ \fBpkgmerge -p dev -s arch=sparc,http://src1.example.com \e\fR
+\fB-s arch=i386,http://src2.example.com \e\fR
+\fB-d /\fIpath/to/target/repository\fR\fR
+.fi
+.in -2
+.sp
+
 .SH EXIT STATUS
 .sp
 .LP
@@ -418,4 +444,4 @@
 \fBpkgrepo\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgmogrify.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgmogrify.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgmogrify 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgmogrify \- Image Packaging System manifest transmogrifier
@@ -622,4 +621,4 @@
 \fBpkg\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgrecv.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgrecv.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkgrecv 1 "20 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkgrecv 1 "4 Mar 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgrecv \- Image Packaging System content retrieval utility
 .SH SYNOPSIS
@@ -9,7 +8,8 @@
 .nf
 /usr/bin/pkgrecv [-s \fIsrc_uri\fR] [-a] [-d (\fIpath\fR|\fIdest_uri\fR)]
     [-c \fIcache_dir\fR] [-kr] [-m \fImatch\fR] [-n] [--raw]
-    [--key \fIkeyfile\fR --cert \fIcertfile\fR]
+    [--key \fIsrc_key\fR --cert \fIsrc_cert\fR]
+    [--dkey \fIdest_key\fR --dcert \fIdest_cert\fR]
     (\fIfmri\fR|\fIpattern\fR) ...
 .fi
 
@@ -18,16 +18,22 @@
 /usr/bin/pkgrecv [-s \fIsrc_uri\fR] --newest
 .fi
 
+.LP
+.nf
+/usr/bin/pkgrecv [-s \fIsrc_uri\fR] [-d \fIpath\fR] [-p \fIpublisher\fR ...] 
+    [--key \fIsrc_key\fR --cert \fIsrc_cert\fR] [-n] --clone
+.fi
+
 .SH DESCRIPTION
 .sp
 .LP
-\fBpkgrecv\fR allows the user to retrieve packages from a \fBpkg\fR(5) repository or package archive. \fBpkgrecv\fR can also optionally republish the retrieved packages to a different package repository or archive them. By default, packages are retrieved in package repository format suitable for use with \fBpkg\fR, \fBpkg.depotd\fR, and package publication tools.
+\fBpkgrecv\fR retrieves all versions of each matching \fIfmri\fR or \fIpattern\fR from the \fIsrc_uri\fR \fBpkg\fR(5) repository or package archive and republishes the retrieved packages to the \fIdest_uri\fR package repository or package archive. By default, packages are retrieved in package repository format suitable for use with \fBpkg\fR, \fBpkg.depotd\fR, and package publication tools.
 .sp
 .LP
 Packages that have not changed are not republished. Therefore, the time to update an existing repository depends on the number of new and changed packages.
 .sp
 .LP
-Use the \fB-m\fR option to specify whether to retrieve all timestamps or all versions of each matching package. By default, only the newest version of each matching package is retrieved.
+Use the \fB-m\fR option to specify whether to retrieve all versions of each matching package, or only the newest version of each matching package.
 .sp
 .LP
 If you do not specify \fB\&'*'\fR to be retrieved, you might want to specify the \fB-r\fR option to be sure to retrieve all the dependencies of the specified packages.
@@ -85,7 +91,7 @@
 .ad
 .sp .6
 .RS 4n
-Specify the file system path or URI where the retrieved packages should be republished. If \fB-a\fR is specified, this destination is a new package archive that cannot already exist. If \fB-a\fR is not specified, this destination must be a package repository that already exists. Use the \fBpkgrepo\fR command to create a new package repository. If \fB-d\fR is not specified, the value of \fBPKG_DEST\fR is used. See "Environment Variables" below.
+Specify the file system path or URI where the retrieved packages should be republished. If \fB-a\fR  is specified, this destination is a new package archive that cannot already exist. If \fB-a\fR  is not specified, this destination must be a package repository that already exists. Use the \fBpkgrepo\fR command to create a new package repository. If \fB-d\fR is not specified, the value of \fBPKG_DEST\fR is used. See "Environment Variables" below.
 .RE
 
 .sp
@@ -107,7 +113,17 @@
 .ad
 .sp .6
 .RS 4n
-Control matching behavior using the following values:
+Control which versions of packages are retrieved if \fIpattern\fR is specified or if \fIfmri\fR is not fully specified. For this description, the following four example packages exist in the source specified by the \fB-s\fR option. In these FMRI, the characters between the \fB@\fR and the \fB:\fR denote the numbered package version, and the characters from the \fB:\fR to the end denote the timestamp portion of the version string.
+.sp
+.in +2
+.nf
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.24.0:20120904T180335Z
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.24.0:20120903T170234Z
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.23.0:20120820T165108Z
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.23.0:20120819T155007Z
+.fi
+.in -2
+
 .sp
 .ne 2
 .mk
@@ -116,7 +132,7 @@
 .ad
 .sp .6
 .RS 4n
-Includes all matching timestamps, not just the latest (implies \fBall-versions\fR).
+Retrieve all versions of each matching \fIfmri\fR or \fIpattern\fR (implies \fBall-versions\fR). This is the default behavior if the \fB-m\fR option is not specified. In the example above, all four packages are retrieved.
 .RE
 
 .sp
@@ -127,7 +143,33 @@
 .ad
 .sp .6
 .RS 4n
-Includes all matching versions, not just the latest.
+Retrieve the latest timestamp for each version of each matching \fIfmri\fR or \fIpattern\fR. In the example above, the following two packages are retrieved:
+.sp
+.in +2
+.nf
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.24.0:20120904T180335Z
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.23.0:20120820T165108Z
+.fi
+.in -2
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBlatest\fR\fR
+.ad
+.sp .6
+.RS 4n
+Retrieve only the newest version of each matching \fIfmri\fR or \fIpattern\fR. In the example above, only the following package is retrieved:
+.sp
+.in +2
+.nf
+pkg://solaris/package/[email protected],5.11-0.175.1.0.0.24.0:20120904T180335Z
+.fi
+.in -2
+
 .RE
 
 .RE
@@ -147,6 +189,17 @@
 .ne 2
 .mk
 .na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+Only clone the given publisher. Can be specified multiple times. Only valid with --clone.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-r\fR\fR
 .ad
 .sp .6
@@ -169,22 +222,55 @@
 .ne 2
 .mk
 .na
-\fB\fB--cert\fR \fIcertfile\fR\fR
+\fB\fB--key\fR \fIsrc_key\fR\fR
 .ad
 .sp .6
 .RS 4n
-Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+Specify a client SSL key file to use for package retrieval from the source HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--cert\fR \fIsrc_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from the source HTTPS repository.
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--key\fR \fIkeyfile\fR\fR
+\fB\fB--dkey\fR \fIdest_key\fR\fR
 .ad
 .sp .6
 .RS 4n
-Specify a client SSL key file to use for package retrieval from an HTTPS repository.
+Specify a client SSL key file to use for package publication to the destination HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--dcert\fR \fIdest_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package publication to the destination HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--clone\fR\fR
+.ad
+.sp .6
+.RS 4n
+Make an exact copy of the source repository. By default, the clone operation will only succeed if publishers in the source repository are also present in the destination. By using \fB-p\fR, the operation can be limited to specific publishers which will be added to the destination repository if not already present. Packages in the destination repository which are not in the source will be removed. Cloning will leave the destination repository altered in case of an error. It is therefore strongly advised to have the destination repository in its own zfs dataset and to take a snapshot before cloning.
 .RE
 
 .sp
@@ -491,7 +577,7 @@
 \fBpkgrepo\fR(1), \fBpkgsend\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fICopying and Creating Oracle Solaris 11.2 Package Repositories\fR
+\fICopying and Creating Oracle Solaris 11.1 Package Repositories\fR
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgrepo.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgrepo.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgrepo 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgrepo \- Image Packaging System repository management utility
@@ -19,31 +18,35 @@
 .LP
 .nf
 /usr/bin/pkgrepo get [-F \fIformat\fR] [-H] [-p \fIpublisher\fR]...
-    -s \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
+    [\fIsection/property\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo info [-F \fIformat\fR] [-H] [-p \fIpublisher\fR]...
-    -s \fIrepo_uri_or_path\fR
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo list [-F \fIformat\fR] [-H] [-p \fIpublisher\fR]...
-    -s \fIrepo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
+    [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo rebuild [-p \fIpublisher\fR]...
-    -s \fIrepo_uri_or_path\fR [--no-catalog] [--no-index]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
+    [--no-catalog] [--no-index]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo refresh [-p \fIpublisher\fR]...
-    -s \fIrepo_uri_or_path\fR [--no-catalog] [--no-index]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
+    [--no-catalog] [--no-index]
 .fi
 
 .LP
@@ -187,7 +190,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo get\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]\fR
+\fB\fBpkgrepo get\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]... [\fIsection/property\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -252,6 +255,17 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Use the \fB--key\fR option to specify a client SSL key file to use for package retrieval from an HTTPS repository. Use the \fB--cert\fR option to specify a client SSL certificate file to use for package retrieval from an HTTPS repository. This option pair can be specified multiple times.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fIsection/property\fR\fR
 .ad
 .sp .6
@@ -265,7 +279,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo info\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR\fR
+\fB\fBpkgrepo info\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]...\fR
 .ad
 .sp .6
 .RS 4n
@@ -288,7 +302,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo list\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]\fR
+\fB\fBpkgrepo list\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]... [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -313,7 +327,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
+\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]... [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -358,7 +372,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo refresh\fR [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
+\fB\fBpkgrepo refresh\fR [\fB-p\fR \fIpublisher\fR]... \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]... [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -1070,4 +1084,4 @@
 \fBpkg\fR(1), \fBpkgrecv\fR(1), \fBpkgsend\fR(1), \fBpkg.depotd\fR(1M), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/pkgsend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgsend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgsend 1 "26 Feb 2013" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgsend \- Image Packaging System publication client
@@ -19,8 +18,8 @@
 .LP
 .nf
 /usr/bin/pkgsend publish [-b \fIbundle\fR]... [-d \fIsource\fR]...
-    [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog]
-    [\fImanifest\fR ...]
+    [-s \fIrepo_uri_or_path\fR] [--key \fIssl_key\fR --cert \fIssl_cert\fR]...
+    [-T \fIpattern\fR] [--no-catalog] [\fImanifest\fR ...]
 .fi
 
 .SH DESCRIPTION
@@ -147,7 +146,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgsend publish\fR [\fB-b\fR \fIbundle\fR]... [\fB-d\fR \fIsource\fR]... [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR
+\fB\fBpkgsend publish\fR [\fB-b\fR \fIbundle\fR]... [\fB-d\fR \fIsource\fR]... [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR]... [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -191,6 +190,17 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR \fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Use the \fB--key\fR option to specify a client SSL key file to use for package retrieval from an HTTPS repository. Use the \fB--cert\fR option to specify a client SSL certificate file to use for package retrieval from an HTTPS repository. This option pair can be specified multiple times.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
@@ -198,7 +208,7 @@
 Do not add the package to the publisher's catalog. This option is recommended whenever multiple packages are being published at one time as updates to publisher catalogs must be performed serially. Once publication is complete, the \fBrefresh\fR subcommand of \fBpkgrepo\fR can be used to add the new packages to the respective publisher catalogs.
 .RE
 
-For a description of the \fB-T\fR option, see the \fBgenerate\fR subcommand above.
+For a descriptions of the \fB-T\fR option, see the \fBgenerate\fR subcommand above.
 .RE
 
 .SH ENVIRONMENT VARIABLES
@@ -376,7 +386,7 @@
 \fBpkgdepend\fR(1), \fBpkgrepo\fR(1), \fBpkg.depotd\fR(1M), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
 .SH NOTES
 .sp
 .LP
--- a/src/man/pkgsign.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pkgsign.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pkgsign 1 "21 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgsign 1 "27 May 2012" "SunOS 5.11" "User Commands"
 .SH NAME
 pkgsign \- Image Packaging System signing utility
 .SH SYNOPSIS
@@ -238,4 +237,4 @@
 \fBpkg\fR(1), \fBpkgrecv\fR(1), \fBpkgsend\fR(1), \fBpkgrepo\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/man/pkgsurf.1	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,257 @@
+'\" te
+.\" Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+.TH pkgsurf 1 "09 Aug 2013" "SunOS 5.11" "User Commands"
+.SH NAME
+pkgsurf \- Image Packaging System repository re-surfacing utility
+.SH SYNOPSIS
+.LP
+.nf
+/usr/bin/pkgsurf -s \fItarget_repo\fR -r \fIreference_repo\fR [-n]
+    [-p \fIpublisher_prefix\fR]... [-i \fIname\fR]... [-c \fIpattern\fR]...
+.fi
+
+.SH DESCRIPTION
+.sp
+.LP
+\fBpkgsurf\fR is a package publication tool for replacing packages in a target repository that have not changed since the latest published version in the reference repository. The result is a new version surface of all packages in the target repository.
+.sp
+.LP
+\fBpkgsurf\fR operations are irreversible; the target repository should be stored in its own ZFS dataset and a snapshot of the dataset should be taken before running \fBpkgsurf\fR in case the operation must be reverted.
+.sp
+.LP
+Packages in the target repository are compared to a given reference repository and analyzed for content changes. If no content change can be determined, the package manifest will be removed from the target repository and replaced with that of the reference repository. Afterwards, the dependencies of all packages in the repository are adjusted to reflect the version changes and keep the integrity of the repository intact.
+.sp
+.LP
+The target repository must be filesystem-based and should only contain one version of each package. If the target repository contains a package which is newer than the latest version in the reference repository and older than the latest version in the target repository, no package version replacement will occur for that package.  For optimal performance, the reference repository should also be filesystem-based.
+.sp
+.LP
+The reference repository may contain one or more versions of each package, however, only the latest version will be used for comparison.
+.SH OPTIONS
+.sp
+.LP
+The following options are supported:
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIpattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+Treat every package whose FMRI matches 'pattern' as changed and do not reversion it, even if there is no content change. Can be specified multiple times.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+Perform a trial run with no changes made to the target repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-i\fR \fIname\fR\fR
+.ad
+.sp .6
+.RS 4n
+Ignore set actions with the name field set to \fIname\fR for determination of content change. Package will be reversioned even if this action differs between target and reference version. Can be specified multiple times.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher_prefix\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the name of the publisher to be re-surfaced. This option can be specified multiple times.
+.sp
+By default, packages from all publishers found in target and reference repositories are re-surfaced.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR \fIreference_repo\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify the URI of the reference repository to be used for manifest comparison. Only the latest version of each package is considered.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fItarget_repo\fR\fR
+.ad
+.sp .6
+.RS 4n
+Path to target repository. Packages in this repository get reversioned to the versions present in the reference repository. Repository should only contain one version of each package. Must be a filesystem-based repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+Display a usage message.
+.RE
+
+.SH ENVIRONMENT VARIABLES
+.sp
+.LP
+The following environment variable is supported:
+.sp
+.ne 2
+.mk
+.na
+\fB\fBPKG_REPO\fR\fR
+.ad
+.RS 10n
+.rt  
+The absolute path of the target repository.
+.RE
+
+.SH EXAMPLES
+.LP
+\fBExample 1 \fRRe-surface repository
+.sp
+.LP
+Reversion each package in the target repository which did not have any content change from the same package in the reference repository.
+
+.sp
+.in +2
+.nf
+$ \fBpkgsurf -s /path/to/target \e\fR
+\fB-r http://reference.example.com\fR
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+Sample package in target:
+
+.sp
+.in +2
+.nf
+set name=pkg.fmri value=pkg://example.com/[email protected]:20381001T163427Z
+dir group=sys mode=0755 owner=root path=usr
+.fi
+.in -2
+
+.sp
+.LP
+Sample package in reference:
+
+.sp
+.in +2
+.nf
+set name=pkg.fmri value=pkg://example.com/[email protected]:20381001T163427Z
+dir group=sys mode=0755 owner=root path=usr
+.fi
+.in -2
+
+.sp
+.LP
+Sample package in target after operation:
+
+.sp
+.in +2
+.nf
+set name=pkg.fmri value=pkg://example.com/[email protected]:20381001T163427Z
+dir group=sys mode=0755 owner=root path=usr
+.fi
+.in -2
+
+
+.SH EXIT STATUS
+.sp
+.LP
+The following exit values are returned:
+.sp
+.ne 2
+.mk
+.na
+\fB\fB0\fR\fR
+.ad
+.RS 6n
+.rt  
+Command succeeded.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB1\fR\fR
+.ad
+.RS 6n
+.rt  
+An error occurred.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB2\fR\fR
+.ad
+.RS 6n
+.rt  
+Invalid command line options were specified.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB99\fR\fR
+.ad
+.RS 6n
+.rt  
+An unanticipated exception occurred.
+.RE
+
+.SH ATTRIBUTES
+.sp
+.LP
+See \fBattributes\fR(5) for descriptions of the following attributes:
+.sp
+
+.sp
+.TS
+tab() box;
+cw(2.75i) |cw(2.75i) 
+lw(2.75i) |lw(2.75i) 
+.
+ATTRIBUTE TYPEATTRIBUTE VALUE
+_
+Availability\fBpackage/pkg\fR
+_
+Interface StabilityUncommitted
+.TE
+
+.SH SEE ALSO
+.sp
+.LP
+\fBpkgrepo\fR(1), \fBpkg\fR(5)
+.sp
+.LP
+\fBhttps://java.net/projects/ips\fR
--- a/src/man/pm-updatemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/pm-updatemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,7 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2013, Oracle and/or its
-.\" affiliates. All rights reserved.
-.TH pm-updatemanager 1 "21 May 2013" "SunOS 5.11" "User Commands"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pm-updatemanager 1 "27 May 2012" "SunOS 5.11" "User Commands"
 .SH NAME
 pm-updatemanager \- application to update packages
 .SH SYNOPSIS
@@ -170,7 +169,7 @@
 \fBpackagemanager\fR(1), \fBpkg\fR(1), \fBpkg\fR(5)
 .sp
 .LP
-\fBhttps://java.net/projects/ips/pages/Home\fR
+\fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
 .SH NOTES
 .sp
 .LP
--- a/src/man/zh_CN/packagemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/packagemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH packagemanager 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH packagemanager 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 packagemanager \- 映像包管理系统的 GUI
 .SH 用法概要
@@ -11,9 +11,9 @@
 
 .LP
 .nf
-/usr/bin/packagemanager [-hiRu] [--help]
-    [--info-install \fIfile\fR] [--update-all]
-    [--image-dir \fIdir\fR]
+/usr/bin/packagemanager [-h | --help]
+    [-i | --info-install \fIfile\fR] [-U | --update-all]
+    [-R | --image-dir \fIdir\fR]
 .fi
 
 .LP
@@ -57,7 +57,11 @@
 .ne 2
 .mk
 .na
-\fB\fB-h\fR 或 \fB--help\fR\fR
+\fB\fB-h\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -68,18 +72,26 @@
 .ne 2
 .mk
 .na
-\fB\fB-i\fR 或 \fB--info-install\fR\fI file\fR\fR
+\fB\fB-i\fR \fIfile\fR\fR
+.ad
+.br
+.na
+\fB\fB--info-install\fR \fIfile\fR\fR
 .ad
 .sp .6
 .RS 4n
-允许指定 \fB\&.p5i\fR 文件以在 Web 安装模式下运行 \fB packagemanager\fR。\fIfile\fR 必须具有后缀 \fB\&.p5i\fR。
+指定 \fB\&.p5i\fR 文件以在 Web 安装模式下运行 \fBpackagemanager\fR。\fIfile\fR 必须具有后缀 \fB\&.p5i\fR。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-R\fR 或 \fB--image-dir\fR\fI dir\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
+.ad
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -90,7 +102,11 @@
 .ne 2
 .mk
 .na
-\fB\fB-U\fR 或 \fB--update-all\fR\fR
+\fB\fB-U\fR\fR
+.ad
+.br
+.na
+\fB\fB--update-all\fR\fR
 .ad
 .sp .6
 .RS 4n
--- a/src/man/zh_CN/pkg.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkg.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkg 1 "2011 年 8 月 30 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkg 1 "2012 年 6 月 26 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkg \- 映像包管理系统的检索客户端
 .SH 用法概要
@@ -11,31 +11,34 @@
 
 .LP
 .nf
-/usr/bin/pkg refresh [--full] [\fIpublisher\fR ...]
+/usr/bin/pkg refresh [-q] [--full] [\fIpublisher\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg install [-nvq] [-g \fIpath_or_uri\fR ...] [--accept]
-    [--licenses] [--no-be-activate] [--no-index] [--no-refresh]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg install [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
+    [--accept] [--licenses] [--no-be-activate] [--no-index]
+    [--no-refresh] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     [--reject \fIpkg_fmri_pattern\fR ...] \fIpkg_fmri_pattern\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg uninstall [-nvq] [--no-be-activate] [--no-index]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg uninstall [-nvq] [-C \fIn\fR] [--no-be-activate]
+    [--no-index] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fIpkg_fmri_pattern\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg update [-fnvq] [-g \fIpath_or_uri\fR ...] [--accept]
-    [--licenses] [--no-be-activate] [--no-index] [--no-refresh]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+/usr/bin/pkg update [-fnvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
+    [--accept] [--licenses] [--no-be-activate] [--no-index]
+    [--no-refresh] [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     [--reject \fIpkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...]
 .fi
@@ -56,7 +59,7 @@
 .nf
 /usr/bin/pkg contents [-Hmr] [-a \fIattribute\fR=\fIpattern\fR ...]
     [-g \fIpath_or_uri\fR ...] [-o \fIattribute\fR ...] [-s \fIsort_key\fR]
-    [-t \fIaction_type\fR ...] [\fIpkg_fmri_pattern\fR ...]
+    [-t \fIaction_name\fR ...] [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
@@ -72,13 +75,15 @@
 
 .LP
 .nf
-/usr/bin/pkg fix [--accept] [--licenses] [\fIpkg_fmri_pattern\fR ...]
+/usr/bin/pkg fix [--accept] [--licenses]
+    [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkg revert [-nv] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     (--tagged \fItag-name\fR ... | \fIpath-to-file\fR ...)
 .fi
@@ -92,7 +97,8 @@
 .nf
 usr/bin/pkg set-mediator [-nv] [-I \fIimplementation\fR]
     [-V \fIversion\fR] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fImediator\fR ...
 .fi
@@ -100,37 +106,40 @@
 .LP
 .nf
 /usr/bin/pkg unset-mediator [-nvIV] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
     \fImediator\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg variant [-H] [\fIvariant_spec\fR]
+/usr/bin/pkg variant [-H] [variant.\fIvariant_name\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg change-variant [-nvq] [-g \fIpath_or_uri\fR ...]
+/usr/bin/pkg change-variant [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
     [--accept] [--licenses] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
     [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
-    \fIvariant_spec\fR=\fIinstance\fR ...
+    \fIvariant_name\fR=\fIvalue\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkg facet [-H] [\fIfacet_spec\fR]
+/usr/bin/pkg facet [-H] [\fIfacet_name\fR ...]
 .fi
 
 .LP
 .nf
-/usr/bin/pkg change-facet [-nvq] [-g \fIpath_or_uri\fR ...]
+/usr/bin/pkg change-facet [-nvq] [-C \fIn\fR] [-g \fIpath_or_uri\fR ...]
     [--accept] [--licenses] [--no-be-activate]
-    [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR]
-    [--deny-new-be | --require-new-be] [--be-name \fIname\fR] 
-    \fIfacet_spec\fR=[True|False|None] ...
+    [--no-backup-be | --require-backup-be]
+    [--backup-be-name \fIname\fR]
+    [--deny-new-be | --require-new-be] [--be-name \fIname\fR]
+    \fIfacet_name\fR=[True|False|None] ...
 .fi
 
 .LP
@@ -180,7 +189,7 @@
 
 .LP
 .nf
-/usr/bin/pkg publisher [-HPn] [\fIpublisher\fR ...]
+/usr/bin/pkg publisher [-HPn] [-F \fIformat\fR] [\fIpublisher\fR ...]
 .fi
 
 .LP
@@ -190,18 +199,32 @@
     [-G \fIorigin_to_remove\fR | --remove-origin \fIorigin_to_remove\fR ...]
     [-m \fImirror_to_add\fR | --add-mirror \fImirror_to_add\fR ...]
     [-M \fImirror_to_remove\fR | --remove-mirror \fImirror_to_remove\fR ...]
-    [-p \fIrepo_uri\fR] [--enable] [--disable] [--no-refresh]
-    [--reset-uuid] [--non-sticky] [--sticky]
-    [--search-after \fIpublisher\fR] [--search-before \fIpublisher\fR]
-    [--search-first]
+    [--enable] [--disable] [--no-refresh] [--reset-uuid]
+    [--non-sticky] [--sticky] [--search-after \fIpublisher\fR]
+    [--search-before \fIpublisher\fR] [--search-first]
     [--approve-ca-cert \fIpath_to_CA\fR]
     [--revoke-ca-cert \fIhash_of_CA_to_remove\fR]
     [--unset-ca-cert \fIhash_of_CA_to_remove\fR]
     [--set-property \fIname_of_property\fR=\fIvalue\fR]
     [--add-property-value \fIname_of_property\fR=\fIvalue_to_add\fR]
     [--remove-property-value \fIname_of_property\fR=\fIvalue_to_remove\fR]
-    [--unset-property \fIname_of_property_to_delete\fR]
-    [\fIpublisher\fR]
+    [--unset-property \fIname_of_property_to_delete\fR] 
+    [--proxy \fIproxy_to_use\fR] \fIpublisher\fR
+.fi
+
+.LP
+.nf
+/usr/bin/pkg set-publisher -p \fIrepo_uri\fR [-Ped]
+    [-k \fIssl_key\fR] [-c \fIssl_cert\fR] [--non-sticky] [--sticky]
+    [--search-after \fIpublisher\fR] [--search-before \fIpublisher\fR
+    [--search-first] [--approve-ca-cert \fIpath_to_CA\fR]
+    [--revoke-ca-cert \fIhash_of_CA_to_remove\fR]
+    [--unset-ca-cert \fIhash_of_CA_to_remove\fR]
+    [--set-property \fIname_of_property\fR=\fIvalue\fR]
+    [--add-property-value \fIname_of_property\fR=\fIvalue_to_add\fR]
+    [--remove-property-value \fIname_of_property\fR=\fIvalue_to_remove\fR]
+    [--unset-property \fIname_of_property_to_delete\fR] 
+    [--proxy \fIproxy_to_use\fR] [\fIpublisher\fR]
 .fi
 
 .LP
@@ -211,7 +234,7 @@
 
 .LP
 .nf
-/usr/bin/pkg history [-Hl] [-t [\fItime\fR | \fItime\fR-\fItime\fR],...]
+/usr/bin/pkg history [-HNl] [-t [\fItime\fR | \fItime\fR-\fItime\fR],...]
     [-o \fIcolumn\fR,...] [-n \fInumber\fR]
 .fi
 
@@ -244,18 +267,19 @@
 .nf
 /usr/bin/pkg image-create [-FPUfz] [--force]
     [--full | --partial | --user] [--zone]
-    [-k \fIssl_key\fR] [-c \fIssl_cert\fR]
-    [--no-refresh] [--variant \fIvariant_spec\fR=\fIinstance\fR ...]
+    [-k \fIssl_key\fR] [-c \fIssl_cert\fR] [--no-refresh]
+    [--variant \fIvariant_name\fR=\fIvalue\fR ...]
     [-g \fIpath_or_uri\fR | --origin \fIpath_or_uri\fR ...]
     [-m \fIuri\fR | --mirror \fIuri\fR ...]
-    [--facet \fIfacet_spec\fR=(True|False) ...]
+    [--set-property \fIname_of_property\fR=\fIvalue\fR]
+    [--facet \fIfacet_name\fR=(True|False) ...]
     [(-p | --publisher) [\fIname\fR=]\fIrepo_uri\fR] \fIdir\fR
 .fi
 
 .SH 描述
 .sp
 .LP
-\fBpkg\fR 是映像包管理系统的检索客户端。在有效配置下,可以调用 \fBpkg\fR 来为要安装的软件包创建位置(称为"映像"),然后将软件包安装到这些映像中。软件包由发布者发布。发布者可使其软件包在一个或多个系统信息库上可用,或者在软件包归档中可用。\fBpkg\fR 从发布者的系统信息库或软件包归档中检索软件包,然后将软件包安装到映像中。
+\fBpkg\fR 是映像包管理系统的检索客户端。在有效配置下,可以调用 \fBpkg\fR 来为要安装的软件包创建位置(称为“映像”),然后将软件包安装到这些映像中。软件包由发布者发布。发布者可使其软件包在一个或多个系统信息库上可用,或者在软件包归档中可用。\fBpkg\fR 从发布者的系统信息库或软件包归档中检索软件包,然后将软件包安装到映像中。
 .sp
 .LP
 发布者名称将个人、个人组或组织标识为一个或多个软件包的源。为避免发布者名称冲突并有帮于标识发布者,最佳做法是使用代表发布软件包实体的域名作为发布者名称。
@@ -276,22 +300,30 @@
 .ne 2
 .mk
 .na
-\fB\fB-R\fR \fIdir\fR\fR
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
 .ad
 .sp .6
 .RS 4n
-对根目录为 \fIdir\fR 的映像执行操作。如果未根据环境指定或确定目录,则缺省值为 /。有关更多信息,请参见"环境变量"部分。
+显示用法消息。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR 或 \fB-?\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
+.ad
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示用法消息。
+对根目录为 \fIdir\fR 的映像进行操作。如果未根据环境指定或确定目录,则缺省值为 /。有关更多信息,请参见“环境变量”部分。
 .RE
 
 .SH 子命令
@@ -302,115 +334,334 @@
 .ne 2
 .mk
 .na
-\fB\fBrefresh [\fB--full\fR] [\fIpublisher \fR ...]\fR\fR
+\fB\fBpkg refresh\fR [\fB-q\fR] [\fB- -full\fR] [\fIpublisher\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+对于所有发布者,更新客户机可用软件包列表和发布者元数据。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅对指定的发布者,更新客户机可用软件包列表和发布者元数据。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+在执行请求的操作期间隐藏进度消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--full\fR\fR
+.ad
+.sp .6
+.RS 4n
+强制完全检索所有发布者元数据(而不是尝试增量更新),并请求操作期间使用的所有代理忽略高速缓存的数据。此选项用于进行故障排除,正常情况下不应使用。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg install\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [\fB--no-backup-be\fR | \fB--require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fI name\fR] [\fB--reject\fR \fIpkg_fmri_pattern\fR ...] \fI pkg_fmri_pattern\fR ...\fR
+.ad
+.sp .6
+.RS 4n
+安装指定软件包并将其更新到最新版本,该版本与映像中安装的软件包所允许的 \fIpkg_fmri_pattern\fR 匹配。要显式请求安装软件包的最新版本,请在 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
+.sp
+软件包基于发布者搜索顺序和粘性进行选择。有关搜索顺序和粘性的信息,请参见 \fBpkg publisher\fR 和 \fBpkg set-publisher\fR 命令。如果 \fIpkg_fmri_pattern\fR 未指定发布者,则会将第一个提供匹配软件包的发布者用作安装源。如果该发布者未提供可以安装在此映像中的软件包版本,则安装操作将失败。使用 \fBpkg list -a\fR 命令可查看哪些发布者提供可以安装在此映像中的软件包版本。
+.sp
+指定了多个 \fIpkg_fmri_pattern\fR 时,如果指定的软件包中有任何一个无法在此映像中安装,则指定的所有软件包都不会安装。
+.sp
+安装过程中,某些配置文件可能被重命名或替换。有关软件包系统如何确定要保留的文件,以及在软件包操作期间如何保留这些文件的更多信息,请参见 \fBpkg\fR(5) 手册页中的“文件操作”。
+.sp
+如果某个软件包在避免列表中,则安装该软件包会将它从该列表中删除。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+暂时将指定的软件包系统信息库或归档文件添加到从中检索软件包数据的映像的源列表内。需要客户机 SSL 证书的系统信息库不能与此选项一起使用。可以多次指定此选项。
+.sp
+确定要使用的软件包版本时,优先选择映像中配置的发布者,而非指定 \fIpath_or_uri\fR 源中找到的发布者。如果映像中配置的发布者和 \fIpath_or_uri\fR 源都提供要安装的软件包版本,则客户机将从 \fIpath_or_uri\fR 源中检索该软件包的内容。安装或更新后,未在映像中配置的发布者提供的所有软件包都将添加到映像配置中,但添加的这些软件包没有源。使用 \fBpkg publisher\fR 命令可查看在映像中配置的发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
 .ad
 .sp .6
 .RS 4n
-对于每个指定的发布者,更新客户端可用软件包列表和发布者元数据。如果未指定任何发布者,则针对所有发布者执行此操作。
-.sp
-使用 \fB--full\fR 时,会强制完全检索所有发布者元数据(而不是尝试增量更新),并请求操作期间使用的所有代理忽略高速缓存的数据。此选项用于进行故障排除,正常情况下不应使用。
+试运行操作而不进行软件包更改。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+在执行请求的操作期间发出详细进度消息,并显示详细的规划信息(例如更改侧面、中介和变量)。可以多次指定此选项,以增加显示的规划信息量。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+在执行请求的操作期间隐藏进度消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-C\fR \fIn\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定要并行更新的子映像数。在递归检查子映像(通常为区域)时,最多可以并行更新 \fIn\fR 个子映像。并行更新的缺省子映像数为 1。如果 \fIn\fR 为 0 或负数,则并行更新所有子映像。另请参见“环境变量”部分中的 \fBPKG_CONCURRENCY\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--accept\fR\fR
+.ad
+.sp .6
+.RS 4n
+表示同意并接受所更新或安装的软件包的许可证条款。如果存在任何需要您接受的软件包许可证,而您未提供此选项,则安装操作将失败。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--licenses\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示在此操作过程中所安装或更新的软件包的所有许可证。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-backup-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+不创建备份引导环境。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-be-activate\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果创建了一个引导环境,不将其设置为下次引导时的活动引导环境。有关更多信息,请参见 \fBbeadm\fR(1M) 手册页。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinstall [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] [\fB--reject\fR \fI pkg_fmri_pattern\fR ...] \fIpkg_fmri_pattern\fR ... \fR\fR
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+不在操作成功完成后更新搜索索引。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+不尝试联系映像发布者的系统信息库来检索最新的可用软件包列表和其他元数据。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--backup-be-name\fR \fIname\fR\fR
 .ad
 .sp .6
 .RS 4n
-安装与映像中安装的软件包所允许的 \fIpkg_fmri_pattern\fR 匹配的软件包,并将其更新到最新版本。要显式请求某个软件包的最新版本,请为 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
-.sp
-安装过程中,某些配置文件可能被重命名或替换。有关软件包系统如何确定要保留的文件,以及在软件包操作期间如何保留这些文件的更多信息,请参见 \fBpkg\fR(5) 中的"文件操作"。
-.sp
-如果某个软件包在避免列表中,则安装该软件包会将它从该列表中删除。
-.sp
-使用 \fB-g\fR 时,会暂时将指定的软件包系统信息库或归档添加到从中检索软件包数据的映像中的源列表内。如果也可以通过映像中配置的发布者使用指定源中的软件包,客户端将仅从指定的源检索这些软件包的内容。确定要使用的软件包版本时,优先选择映像中配置的、但在给定源中找不到的发布者。安装或更新后,在映像中找不到的发布者提供的任何软件包将添加到映像配置中,且添加的软件包没有源。可以多次指定此选项。
-.sp
-使用 \fB-n\fR 时,会试运行操作而不进行软件包更改。
-.sp
-使用 \fB-q\fR 时,会在执行请求的操作期间隐藏进度消息。
-.sp
-使用 \fB-v\fR 时,会在执行请求的操作期间发出详细进度消息,并显示详细的规划信息(例如更改侧面、中介者和变体)。可以多次指定此选项,以增加显示的规划信息量。
-.sp
-使用 \fB--accept\fR 时,表示同意并接受所更新或安装的软件包的许可证条款。如果不提供此选项,且任何软件包许可证都要求接受,则安装操作将失败。
-.sp
-使用 \fB--licenses\fR 时,会在此操作过程中显示已安装或更新的软件包的所有许可证。
-.sp
-使用 \fB--no-backup-be\fR 时,不会创建备份引导环境。
-.sp
-使用 \fB--no-be-activate\fR 时,如果创建了一个引导环境 (boot environment, BE),则下次引导时,不会将该 BE 设置为活动 BE。有关更多信息,请参见 \fBbeadm\fR(1M)。
-.sp
-使用 \fB--no-index\fR 时,不会在操作成功完成后更新搜索索引。
-.sp
-使用 \fB--no-refresh\fR 时,不会尝试联系系统信息库来让映像发布者检索最新的可用软件包列表和其他元数据。
-.sp
-使用 \fB--backup-be-name\fR 时,使用给定参数命名创建的备份引导环境。使用 \fB--backup-be-name\fR 意味着 \fB--require-backup-be\fR。另请参见 \fBbeadm\fR(1M)。
-.sp
-使用 \fB--be-name\fR 时,会将新创建的引导环境重命名为给定的参数。使用 \fB--be-name\fR 意味着 \fB--require-new-be\fR。另请参见 \fBbeadm\fR(1M)。
-.sp
-使用 \fB--require-backup-be\fR 时,如果不创建新的引导环境,则始终创建一个备份引导环境。如果不使用该选项,则根据映像策略创建备份引导环境。有关何时自动创建备份引导环境的说明,请参见下面"映像属性"中的 \fBbe-policy\fR。
-.sp
-使用 \fB--require-new-be\fR 时,始终创建新的引导环境。如果不使用该选项,则根据映像策略创建引导环境。有关何时自动创建引导环境的说明,请参见下列"映像属性"中的 \fBbe-policy\fR。该选项不能与 \fB-require-backup-be\fR 结合使用。
-.sp
-使用 \fB--deny-new-be\fR 时,不会创建新的引导环境。如果需要新的引导环境,则不执行此操作。
-.sp
-使用 \fB--reject\fR 时,会阻止安装其名称与给定模式匹配的软件包。如果已安装匹配的软件包,则在此操作过程会将其删除。作为组依赖性目标的被拒绝软件包将放置在避免列表中。
+使用给定参数命名创建的备份引导环境。使用 \fB--backup-be-name\fR 表示 \fB--require-backup-be\fR。另请参见 \fBbeadm\fR(1M) 手册页。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--be-name\fR \fIname\fR\fR
+.ad
+.sp .6
+.RS 4n
+将新创建的引导环境重命名为给定的参数。使用 \fB--be-name\fR 表示 \fB--require-new-be\fR。另请参见 \fBbeadm\fR(1M) 手册页。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--require-backup-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果不创建新的引导环境,则始终创建一个备份引导环境。如果不使用该选项,则根据映像策略创建备份引导环境。有关何时自动创建备份引导环境的说明,请参见下文“映像属性”中的 \fBbe-policy\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--require-new-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+始终创建新的引导环境。如果不使用该选项,则根据映像策略创建引导环境。有关何时自动创建引导环境的说明,请参见下文“映像属性”中的 \fBbe-policy\fR。该选项不能与 \fB-require-backup-be\fR 一起使用。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--deny-new-be\fR\fR
+.ad
+.sp .6
+.RS 4n
+不创建新的引导环境。如果需要新的引导环境,则不执行此操作。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBuninstall [\fB-nvq\fR] [\fB--no-be-activate \fR] [\fB--no-index\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI pkg_fmri_pattern\fR ...\fR\fR
+\fB\fB--reject\fR \fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+阻止安装名称与给定模式匹配的软件包。如果已安装匹配的软件包,则在此操作过程会将其删除。作为组依赖性目标的被拒绝软件包将放置在避免列表中。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg uninstall\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIpkg_fmri_pattern\fR ... \fR
 .ad
 .sp .6
 .RS 4n
 删除与 \fIpkg_fmri_pattern\fR 匹配的已安装软件包。
 .sp
-如果某个软件包是组依赖性的主体,则卸载该软件包会将它放置在避免列表中。请参见下面的 \fBavoid\fR 子命令。
-.sp
-对于其他所有选项,请参阅上面的 \fBinstall\fR 命令,以了解其用法及效果。
+如果某个软件包是组依赖性的主体,则卸载该软件包会将它放置在避免列表中。请参见下文的 \fBavoid\fR 子命令。
+.sp
+有关选项的说明,请参见上述 \fBinstall\fR 命令。
+.sp
+在命令输出中,请注意任何指出已创建新引导环境的消息。如果已创建并激活新引导环境,缺省情况下,下次重新引导时会引导该环境。有关管理引导环境的信息,请参见 \fBbeadm\fR(1M) 手册页。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBupdate [\fB-fnvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] [\fB--reject\fR \fI pkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg update\fR [\fB-fnvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-index\fR] [\fB--no-refresh \fR] [\fB--no-backup-be\fR | \fB--require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fI name\fR] [\fB--reject\fR \fIpkg_fmri_pattern\fR ...] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-如果不使用任何参数,或者星号 (*) 是提供的模式之一,则将当前映像中安装的所有软件包更新到由安装的软件包和发布者配置强加于系统的约束所允许的最新版本。要显式请求某个软件包的最新版本,请为 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
-.sp
-如果提供了 \fIpkg_fmri_pattern\fR,\fBupdate\fR 将与 \fIpkg_fmri_pattern\fR 匹配的已安装软件包替换为由安装的软件包和发布者配置强加于系统的模式和约束所允许的最新版本。可以指定比已安装版本更高或更低的版本,以便对特定软件包执行就地降级或升级。不支持跨越软件包重命名边界或过时边界更新特定的软件包。
-.sp
-作为将要由 \fBupdate\fR 降级的软件包的一部分、自安装原始版本以来已更改的任何保留配置文件,将会使用扩展名 \fB\&.update\fR 进行重命名。有关软件包系统如何确定要保留的文件,以及在软件包升级期间如何保留这些文件的更多信息,请参见 \fBpkg\fR(5) 中的"文件操作"。
-.sp
-使用 \fB-f\fR 选项时,不会在更新已安装的所有软件包时执行客户端最新状态检查。
-.sp
-对于其他所有选项,请参阅上面的 \fBinstall\fR 命令,以了解其用法及效果。
+将当前映像中安装的所有软件包更新到最新版本,该版本需符合已安装的软件包和发布者配置对系统施加的约束。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅更新当前映像中安装的指定软件包。如果所提供的 \fIpkg_fmri_pattern\fR 模式中包含星号 (*),则会按如上所述更新当前映像中安装的所有软件包。
+.sp
+要显式请求安装软件包的最新版本,请在 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
+.sp
+可以指定比已安装版本更高或更低的版本,以便对特定软件包执行就地降级或升级。不支持跨越软件包重命名边界或过时边界更新特定的软件包。
+.sp
+作为将要降级的软件包的一部分、自原始版本安装以来更改了的任何保留配置文件,将使用扩展名 \fB\&.update\fR 进行重命名。有关软件包系统如何确定要保留的文件,以及在软件包升级期间如何保留这些文件的更多信息,请参见 \fBpkg\fR(5) 手册页中的“文件操作”。
+.sp
+指定了多个 \fIpkg_fmri_pattern\fR 时,如果指定的软件包中有任何一个无法在此映像中更新,则指定的所有软件包都不会更新。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBlist [\fB-Hafnsuv\fR] [\fB-g\fR\fI path_or_uri\fR ...][\fB--no-refresh\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fB-f\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示当前映像中的软件包列表,包括状态和其他信息。缺省情况下,会排除不同体系结构或区域类型的软件包变体。输出通常包括三个列:
+不在更新已安装的所有软件包时执行客户机最新状态检查。
+.RE
+
+对于其他所有选项,请参见上面的 \fBinstall\fR 命令。
+.sp
+在命令输出中,请注意任何指出已创建新引导环境的消息。如果已创建并激活新引导环境,在未指定 \fB--no-be-activate\fR 选项时,缺省情况下,下次重新引导时会引导该环境。有关管理引导环境的信息,请参见 \fBbeadm\fR(1M) 手册页。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg list\fR [\fB-Hafnsuv\fR] [\fB-g\fR \fIpath_or_uri\fR ...] [\fB--no-refresh \fR] [\fIpkg_fmri_pattern\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+显示当前映像中安装的所有软件包的列表,包括版本和安装状态等信息。缺省情况下,会排除不同体系结构或区域类型的软件包变量。输出通常包括三个列:
 .sp
 .in +2
 .nf
-NAME (PUBLISHER)            VERSION           IFO
-system/core-os              0.5.11-0.169      i--
-x11/wm/fvwm (fvwm.org)      2.6.1-3           i--
+NAME (PUBLISHER)       VERSION                IFO
+system/core-os         0.5.11-0.175.0.0.0.2.1 i--
+x11/wm/fvwm (fvwm.org) 2.6.5                  i--
 .fi
 .in -2
 
-第一列包含软件包的名称。如果安装(或者提供)该软件包的发布者在发布者搜索顺序上不是第一个,则该发布者名称将列在软件包名称的后面,并括在括号中。第二列包含软件包的发行版本和分支版本。有关发行版本和分支版本的信息,请参见 \fBpkg\fR(5)。
+第一列包含软件包的名称。如果安装(或者提供)该软件包的发布者在发布者搜索顺序上不是第一个,则该发布者名称将列在软件包名称的后面,并括在括号中。第二列包含软件包的发行版本和分支版本。有关发行版本和分支版本以及变量的信息,请参见 \fBpkg\fR(5) 手册页。
 .sp
 .LP
 最后一列包含一组标志,用于显示软件包的状态:
@@ -432,68 +683,292 @@
 .el o
 \fBO\fR 列中的 \fBo\fR 表明软件包已过时。\fBO\fR 列中的 \fBr\fR 表明软件包已重命名(一种形式的过时)。
 .RE
-使用 \fB-H\fR 时,会省略列表中的标题。
-.sp
-使用 \fB-a\fR 时,会列出已安装的软件包,以及可用于安装的软件包的最新版本。如果软件包得到已安装 incorporation 和映像变体的允许,则认为这些软件包可用于安装。如果指定了一个或多个模式,则会列出与指定模式匹配的、得到任何已安装 incorporation 和映像变体允许的最新版本。如果不使用 \fB-a\fR,则仅列出已安装的软件包。
-.sp
-使用 \fB-f\fR 和 \fB-a\fR 时,会列出所有变体的所有软件包的所有版本,而不管 incorporation 约束或安装状态如何。使用这些选项时,要显式列出某个软件包的最新版本,请为 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
-.sp
-使用 \fB-g\fR 时,会使用指定的软件包系统信息库或归档作为操作的软件包数据源。可以多次指定此选项。如果未指定 \fB-n\fR,则可使用 \fB-g\fR 表示 \fB-a\fR。
-.sp
-使用 \fB-n\fR 时,会显示所有已知软件包的最新版本,而不管安装状态如何。
-.sp
-使用 \fB-s\fR 时,会显示单行短格式,用于提供软件包名称和摘要。此选项可与 \fB-a\fR、\fB-n\fR、\fB-u\fR 或 \fB-v\fR 一起使用。
-.sp
-使用 \fB-u\fR 时,仅列出其更高版本可用的软件包。此选项不能与 \fB-g\fR 一起使用。
-.sp
-使用 \fB-v\fR 时,会在第一列中显示完整的软件包 FMRI,包括发布者和完整版本(VERSION 列将会消失)。此选项可与 \fB-a\fR、\fB-n\fR 或 \fB-u\fR 一起使用。
-.sp
-使用 \fB--no-refresh\fR 时,不会尝试联系系统信息库来让映像发布者检索最新的可用软件包列表。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅列出指定的软件包。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+列出已安装的软件包,以及可用于安装的软件包的最新版本。如果软件包是已安装 incorporation 和映像变量所允许的,则认为这些软件包可用于安装。如果指定了一个或多个模式,则会列出与指定模式匹配的且任何已安装 incorporation 和映像变量允许的最新版本。如果不使用 \fB-a\fR,则仅列出已安装的软件包。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-af\fR\fR
+.ad
+.sp .6
+.RS 4n
+列出所有变量的所有软件包的所有版本,而不管 incorporation 约束或安装状态如何。使用这些选项时,要显式列出某个软件包的最新版本,请在 \fIpkg_fmri_pattern\fR 的版本部分使用 \fBlatest\fR。例如,指定 \fBvim@latest\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用指定的软件包系统信息库或归档文件作为操作的软件包数据源。需要客户机 SSL 证书的系统信息库不能与此选项一起使用。可以多次指定此选项。如果未指定 \fB-n\fR,则可使用 \fB-g\fR 表示 \fB-a\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示所有已知软件包的最新版本,而不管安装状态如何。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示单行短格式,用于提供软件包名称和摘要。此选项可与 \fB-a\fR、\fB-n\fR、\fB-u\fR 或 \fB-v\fR 一起使用。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-u\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅列出有更高版本可用的软件包。此选项不能与 \fB-g\fR 一起使用。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+在第一列中显示完整的软件包 FMRI,包括发布者和完整版本(VERSION 列将消失)。此选项可与 \fB-a\fR、\fB-n\fR 或 \fB-u\fR 一起使用。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+不尝试联系映像发布者的系统信息库来检索最新的可用软件包列表。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg info\fR [\fB-lr\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--license\fR] [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+以用户可读的格式显示当前映像中安装的所有软件包的相关信息。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定软件包的相关信息。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinfo [\fB-lr\fR] [\fB-g\fR\fI path_or_uri\fR ...][\fB--license\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用指定的软件包系统信息库或归档文件作为操作的软件包数据源。需要客户机 SSL 证书的系统信息库不能与此选项一起使用。可以多次指定此选项。使用 \fB-g\fR 表示 \fB-r\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示已安装的软件包的相关信息。这是缺省值。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
 .ad
 .sp .6
 .RS 4n
-以用户可读的格式显示有关软件包的信息。可以指定多个 FMRI 模式。如果未指定模式,则显示映像中所有已安装软件包的相关信息。
-.sp
-使用 \fB-g\fR 时,会使用指定的软件包系统信息库或归档作为操作的软件包数据源。可以多次指定此选项。可使用 \fB-g\fR 表示 \fB-r\fR。
-.sp
-使用 \fB-l\fR 时,仅显示已安装的软件包的信息。这是缺省值。
-.sp
-使用 \fB-r\fR 时,会根据可用的最新版本匹配软件包,并从映像的已配置发布者系统信息库中检索当前未安装的软件包的相关信息(如有必要)。使用此选项时,必须至少指定一个软件包。如果不指定 \fB-r\fR,则缺省情况下仅显示已安装的软件包。
-.sp
-使用 \fB--license\fR 时,会显示软件包的许可证文本。此选项可与 \fB-l\fR 或 \fB-r\fR 结合使用。
+根据最新的可用版本匹配软件包,并从映像中配置的发布者系统信息库检索当前未安装的软件包的相关信息(如有必要)。使用此选项时,必须至少指定一个软件包。如果不指定 \fB-r\fR,则缺省情况下仅显示已安装的软件包。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--license\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示软件包的许可证文本。此选项可与 \fB-l\fR 或 \fB-r\fR 结合使用。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg contents\fR [\fB-Hmr\fR] [\fB-a\fR \fIattribute\fR=\fIpattern\fR ...] [\fB-g\fR \fIpath_or_uri\fR ...] [\fB-o\fR \fI attribute\fR,...] [\fB-s\fR \fIsort_key\fR] [\fB-t\fR \fIaction_name\fR ...] [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+显示映像中安装的所有软件包的内容(操作属性)。未指定选项时,显示当前映像中安装的操作的 \fBpath\fR 属性值,按属性值的字母顺序排列。有关操作及其属性的信息,请参见 \fBpkg\fR(5) 手册页中的“操作”。另请参见以下伪属性名称列表。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定软件包的内容。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBcontents [\fB-Hmr\fR] [\fB-a\fR\fI attribute\fR=\fIpattern\fR ...][\fB-g\fR\fI path_or_uri\fR ...][\fB-o\fR\fIattribute\fR,...][\fB-s\fR\fIsort_key\fR] [\fB-t\fR\fI action_type\fR ...][\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在输出中省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR \fIattribute\fR=\fI pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+将输出限制为特定操作,这些操作具有在选项参数中指定的属性,且其属性值与选项参数中的 (glob) 模式匹配(位于属性名称之后,带一个等号)。如果指定了多个 \fB-a\fR 选项,则会显示与其中任一选项匹配的操作。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示指定软件包系统信息库或归档文件中可以安装在此映像中的软件包的信息。需要客户机 SSL 证书的系统信息库不能与此选项一起使用。可以安装的软件包包含当前已安装的软件包以及其他满足此映像安装条件(例如变量和侧面限制)的软件包。可以多次指定此选项。使用 \fB-g\fR 表示 \fB-r\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示当前映像中软件包的内容(操作属性)。缺省情况下,仅显示 \fBpath\fR 属性。可以使用 \fB-o\fR 选项确定所显示的属性。可以多次指定 \fB-o\fR 选项;也可以通过使用逗号分隔属性名称,将多个属性指定为一个 \fB-o\fR 选项的参数。仅显示包含所请求属性的操作。也可以使用 \fB-m\fR 选项,作为 \fB-Ho action.raw\fR 的简写形式。
-.sp
-使用 \fB-a\fR 时,会将输出限制为在选项参数中带有某个命名属性的那些操作,该属性的值与选项参数中的 (glob) 模式匹配(在属性名称后面添加一个等号)。如果指定了多个 \fB-a\fR 选项,则会显示与其中任一选项匹配的操作。
-.sp
-使用 \fB-g\fR 时,会使用指定的软件包系统信息库或归档作为操作的软件包数据源。可以多次指定此选项。可使用 \fB-g\fR 表示 \fB-r\fR。
-.sp
-使用 \fB-r\fR 时,会根据可用的最新版本匹配软件包,并从映像的已配置发布者系统信息库中检索当前未安装的软件包的相关信息(如有必要)。使用此选项时,必须至少指定一个软件包。如果不指定 \fB-r\fR,则缺省情况下仅显示已安装的软件包。
-.sp
-使用 \fB-s\fR 时,会按指定的操作属性对操作进行排序。如果未提供此选项,则缺省设置是按照路径或者按照 \fB-o\fR 选项指定的第一个属性进行排序。可以多次指定 \fB-s\fR 选项。
-.sp
-使用 \fB-t\fR 时,仅列出指定类型的操作。可以在一个逗号分隔的列表中指定多个类型。可以多次指定此选项。
-.sp
-使用 \fB-H\fR 时,会省略列表中的标题。
-.sp
-如果未指定任何参数,则输出包括所有已安装的软件包。或者,可以指定多个 FMRI 模式,这会将显示内容限制为匹配软件包的内容。使用 \fB-r\fR 时,必须指定一个或多个 \fIpkg_fmri_pattern\fR。
-.sp
+显示指定软件包中所有操作的所有属性,包括无法安装在此映像中的操作。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIattribute\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示指定属性,按列出的第一个属性的值排序。可以多次指定 \fB-o\fR 选项;也可以通过使用逗号分隔属性名称,将多个属性指定为一个 \fB-o\fR 选项的参数。仅显示包含所请求属性的操作。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示此映像中配置的发布者系统信息库中可以安装在此映像中的软件包的最新可用版本信息。可以安装的软件包包含当前已安装的软件包以及其他满足此映像安装条件(例如变量和侧面限制)的软件包。使用此选项时,必须至少指定一个软件包。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIsort_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+按指定的操作属性对操作进行排序。如果未提供此选项,则缺省设置是按照路径进行排序或者按照 \fB-o\fR 选项指定的第一个属性进行排序。可以多次指定 \fB-s\fR 选项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-t\fR \fIaction_name\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅列出指定的操作。可以在一个逗号分隔的列表中指定多个操作。\fIaction_name\fR 的值是 \fBpkg\fR(5) 手册页的“操作”中列出的操作之一,例如 \fBfile\fR、\fBdirectory\fR、\fBdriver\fR、\fBdepend\fR、\fBset\fR。可以多次指定此选项。
+.RE
+
 为方便起见,可以使用多个特殊的伪属性名称:
 .sp
 .ne 2
@@ -501,9 +976,9 @@
 .na
 \fB\fBaction.hash\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于操作的散列值(如果该操作承载了有效负荷)。
+.sp .6
+.RS 4n
+操作的散列值(如果该操作承载了有效负荷)。
 .RE
 
 .sp
@@ -512,9 +987,9 @@
 .na
 \fB\fBaction.key\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于该操作的关键属性值。例如,对于某个文件操作,这是该文件的路径。
+.sp .6
+.RS 4n
+该操作的关键属性值。例如,对于 \fBfile\fR 操作,关键属性是文件的路径。某些操作不具备关键属性。
 .RE
 
 .sp
@@ -523,9 +998,9 @@
 .na
 \fB\fBaction.name\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于操作的名称。例如,对于某个文件操作,这是 \fBfile\fR。
+.sp .6
+.RS 4n
+操作的名称。例如,对于某个文件操作,这是 \fBfile\fR。
 .RE
 
 .sp
@@ -534,9 +1009,9 @@
 .na
 \fB\fBaction.raw\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于软件包清单中所示操作的完整内容。这对应于 \fBpkg contents -m\fR 的输出行。
+.sp .6
+.RS 4n
+匹配操作的所有属性。
 .RE
 
 .sp
@@ -545,9 +1020,9 @@
 .na
 \fB\fBpkg.fmri\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于包含操作的软件包的完整格式 FMRI,例如 \fBpkg://solaris/web/[email protected],5.11-0.169:20110705T153434Z\fR。
+.sp .6
+.RS 4n
+包含操作的软件包的完整 FMRI,例如 \fBpkg://solaris/group/feature/[email protected],5.11-0.175.0.0.0.2.1:20120705T153434Z\fR。
 .RE
 
 .sp
@@ -556,9 +1031,9 @@
 .na
 \fB\fBpkg.name\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于包含操作的软件包的名称,例如 \fBweb/amp\fR。
+.sp .6
+.RS 4n
+包含操作的软件包的名称,例如 \fBweb/amp\fR。
 .RE
 
 .sp
@@ -567,9 +1042,9 @@
 .na
 \fB\fBpkg.publisher\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于包含操作的软件包的发布者,例如 \fBsolaris\fR。
+.sp .6
+.RS 4n
+包含操作的软件包的发布者,例如 \fBsolaris\fR。
 .RE
 
 .sp
@@ -578,12 +1053,12 @@
 .na
 \fB\fBpkg.shortfmri\fR\fR
 .ad
-.RS 17n
-.rt  
-对应于包含操作的软件包的短格式 FMRI,例如 \fBpkg://solaris/web/[email protected],5.11-0.169\fR
+.sp .6
+.RS 4n
+包含操作的软件包的短格式 FMRI,例如 \fBpkg://solaris/group/feature/[email protected],5.11-0.175\fR。
 .RE
 
-\fBcontents\fR 和 \fBsearch\fR 子命令是彼此相关的:两者都可用于在系统中查询软件包的内容。\fBcontents\fR 子命令显示一个或多个软件包中的操作,根据用户选择的选项过滤输出。\fBsearch\fR 子命令从另一个方向处理查询,查找包含用户提供的标记的软件包。
+\fBcontents\fR 和 \fBsearch\fR 子命令是彼此相关的:两者都可在系统中查询软件包的内容。\fBcontents\fR 子命令显示一个或多个已安装或可安装软件包中的操作,根据指定的选项过滤输出。\fBsearch\fR 子命令从另一个方向处理查询,显示包含用户提供的标记的所有软件包的名称。
 .sp
 每个子命令都能够表达另一个子命令也能表达的某些查询。应该谨慎选择所需的子命令,因为使用其中一个子命令来表达某个给定查询,可能比使用另一个子命令更为自然。
 .RE
@@ -592,32 +1067,110 @@
 .ne 2
 .mk
 .na
-\fB\fBsearch [\fB-HIaflpr\fR] [\fB-o\fR\fI attribute\fR,...][\fB-s\fR\fIrepo_uri\fR] \fI query\fR\fR\fR
+\fB\fBpkg search\fR [\fB-HIaflpr\fR] [\fB-o\fR \fIattribute\fR,...] [\fB-s\fR \fI repo_uri\fR] \fIquery\fR\fR
+.ad
+.sp .6
+.RS 4n
+搜索 \fIquery\fR 的匹配项并显示结果。请参见下文的 \fIquery\fR 说明。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在输出中省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用区分大小写的搜索。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+执行搜索并显示有关匹配操作的信息。这是缺省值。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-f\fR\fR
 .ad
 .sp .6
 .RS 4n
-搜索 \fIquery\fR 的匹配项并显示结果。要为哪些标记建立索引是与操作相关的,不过可以包括内容散列和路径名称。缺省情况下,会将查询解释为要精确匹配的一系列条件。可将 \fB?\fR 和 \fB*\fR 字符用作 \fBglob\fR(3C) 式通配符,以更灵活地获取查询匹配项。
-.sp
-使用 \fB-H\fR 时,会省略标题。
-.sp
-使用 \fB-I\fR 时,会使用区分大小写的搜索。
-.sp
-缺省情况下,使用 \fB-a\fR 时,会执行搜索并显示有关匹配操作的信息。
-.sp
-缺省情况下,\fBsearch\fR 会删改低于当前安装版本的软件包中的结果,以及当前 incorporation 排除的软件包版本中的结果。使用 \fB-f\fR 可显示所有结果,而不管软件包版本如何。
-.sp
-使用 \fB-l\fR 时,会搜索映像的已安装软件包。
-.sp
-使用 \fB-o\fR 时,可以控制结果的各列。可以多次指定 \fB-o\fR 选项;也可以通过使用逗号分隔属性名称,将多个属性指定为一个 \fB-o\fR 选项的参数。除了上面概述的伪属性外,还为搜索结果定义了下列属性:
+显示所有结果,而不考虑软件包版本。缺省情况下,\fBsearch\fR 会从结果中去除低于当前安装版本的软件包以及当前 incorporation 中排除的软件包版本。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
+.ad
+.sp .6
+.RS 4n
+搜索映像的已安装软件包。
+.sp
+可以同时指定 \fB-l\fR 和 \fB-r\fR(或 \fB-s\fR),在此情况下,将会同时执行本地搜索和远程搜索。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示其某些操作与每个查询词匹配的软件包。使用此选项相当于在查询中的每个词两侧添加尖括号 (\fB<>\fR)。有关 \fB<>\fR 运算符的更多说明,请参见下文的 \fIquery\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-r\fR\fR
+.ad
+.sp .6
+.RS 4n
+搜索对应于映像发布者的系统信息库。这是缺省值。
+.sp
+可以同时指定 \fB-l\fR 和 \fB-r\fR(或 \fB-s\fR),在此情况下,将会同时执行本地搜索和远程搜索。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIattribute\fR\fR
+.ad
+.sp .6
+.RS 4n
+控制结果列。可以多次指定 \fB-o\fR 选项;也可以通过使用逗号分隔属性名称,将多个属性指定为一个 \fB-o\fR 选项的参数。除了上面概述的伪属性外,还为搜索结果定义了下列属性:
 .sp
 .ne 2
 .mk
 .na
 \fB\fBsearch.match\fR\fR
 .ad
-.RS 21n
-.rt  
-对应于与搜索查询匹配的字符串。
+.sp .6
+.RS 4n
+与搜索查询匹配的字符串。
 .RE
 
 .sp
@@ -626,261 +1179,638 @@
 .na
 \fB\fBsearch.match_type\fR\fR
 .ad
-.RS 21n
-.rt  
-对应于包含与搜索查询匹配的字符串的属性。
+.sp .6
+.RS 4n
+包含与搜索查询匹配的字符串的属性。
+.RE
+
 .RE
 
-使用 \fB-p\fR 时,会显示其某些操作与每个查询词匹配的软件包。使用此选项相当于在查询中的每个词两侧添加尖括号 (\fB<>\fR)。有关 \fB<>\fR 运算符的更多描述,请参见下文。
-.sp
-缺省情况下,使用 \fB-r\fR 时,会搜索对应于映像发布者的系统信息库。
-.sp
-使用 \fB-s\fR 时,会搜索位于给定 URI 的 \fBpkg\fR(5) 系统信息库。可以多次指定此选项。不支持软件包归档。
-.sp
-可以同时指定 \fB-l\fR 和 \fB-r\fR(或 \fB-s\fR),在此情况下,将会同时执行本地搜索和远程搜索。
-.sp
-除了支持简单的标记匹配和通配符搜索外,还支持更复杂的查询语言。可通过使用单引号或双引号(\fB\&'\fR 或 \fB"\fR)来搜索短语。请务必考虑所用的 shell,使 \fBpkg\fR 能够真正识别 \fB\&'\fR 或 \fB"\fR。
-.sp
-支持使用 AND 和 OR 的布尔搜索。支持字段(或结构化)查询。这些命令的语法为 \fB\fIpkg_name\fR:\fIaction_type\fR:\fIkey\fR:\fItoken\fR\fR。对缺少的字段使用隐式通配符。搜索 \fB:basename:pkg\fR 将会匹配包含关键字 \fBbasename\fR 且与标记 \fBpkg\fR 匹配的所有软件包中的所有操作类型。\fBpkg_name\fR 和 \fBtoken\fR 字段中支持显式通配符。\fBaction_type\fR 和 \fBkey\fR 必须完全匹配。
-.sp
-要将操作转换为包含这些操作的软件包,请使用 \fB<>\fR。使用 \fB-a\fR 选项时,搜索 \fBtoken\fR 会导致返回与 \fBtoken\fR 匹配的操作的相关信息,而搜索 \fB<token>\fR 会导致返回一个软件包列表,这些软件包包含与 \fBtoken\fR 匹配的操作。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+搜索位于给定 URI 的 \fBpkg\fR(5) 系统信息库。可以多次指定此选项。不支持软件包归档。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBverify [\fB-Hqv\fR] [\fIpkg_fmri_pattern \fR ...]\fR\fR
+\fB\fIquery\fR\fR
 .ad
 .sp .6
 .RS 4n
-验证当前映像中的软件包安装。如果相关发布者的当前签名策略不是 \fBignore\fR,则会根据策略验证每个软件包的签名。有关如何应用签名策略的说明,请参见下面的"映像属性"中的 \fBsignature-policy\fR。
-.sp
-使用 \fB-H\fR 时,会省略验证输出中的标题。
-.sp
-使用 \fB-q\fR 时,如果出现任何致命错误,则不会显示任何信息,但会返回失败消息。
-.sp
-使用 \fB-v\fR 时,会包括有关软件包的提示性消息。
+缺省情况下,会将 \fIquery\fR 解释为要精确匹配的一系列条件。可将 \fB?\fR 和 \fB*\fR 字符用作 \fBglob\fR(3C) 式通配符,以更灵活地获取查询匹配项。
+.sp
+除了支持简单的标记匹配和通配符搜索外,还支持更复杂的查询语言。可通过使用单引号或双引号(\fB\&'\fR 或 \fB"\fR)来搜索短语。请务必考虑所用的 shell,使 \fBpkg\fR 能够真正识别 \fB\&'\fR 或 \fB"\fR。
+.sp
+支持使用 AND 和 OR 的布尔搜索。
+.sp
+要为哪些标记建立索引是与操作相关的,不过可以包括内容散列和路径名称。有关操作及其属性的信息,请参见 \fBpkg\fR(5) 手册页中的“操作”。另请参见上面 \fBpkg contents\fR 和 \fB-o\fR 中的伪属性名称列表。
+.sp
+结构化查询支持以下语法:
+.sp
+.in +2
+.nf
+\fIpkg_name\fR:\fIaction_name\fR:\fIindex\fR:\fItoken\fR
+.fi
+.in -2
+
+\fIaction_name\fR 的值是 \fBpkg\fR(5) 手册页的“操作”中列出的操作之一。\fIindex\fR 是操作的属性。\fIindex\fR 的值必须与 \fItoken\fR 匹配。
+.sp
+并非所有操作属性都是可搜索的。例如,\fBmode\fR 是 \fBfile\fR 操作的一个属性,但是 \fBmode\fR 不是 \fIindex\fR 的有效值。
+.sp
+\fIindex\fR 的某些值并不是操作属性,而是从其他属性派生的值。例如,\fIindex\fR 可以是 \fBbasename\fR,其不是任何操作的属性,而是派生自 \fBfile\fR 或 \fBdir\fR 操作的 \fBpath\fR 属性,它采用了路径的最后组成部分。
+.sp
+不同的操作类型有不同的 \fIindex\fR 有效值。本文档并未列出所有可能的值。一些更为有用的 \fIindex\fR 值包括,对应于文件系统操作的 \fBbasename\fR 和 \fBpath\fR、对应于 \fBdepend\fR 操作的依赖性类型(例如 \fBrequire\fR、\fBoptional\fR、\fBgroup\fR),以及对应于 \fBdriver\fR 操作的 \fBdriver_name\fR 和 \fBalias\fR。
+.sp
+\fIindex\fR 的一个特殊值是对应于 \fBset\fR 操作的 \fBname\fR 属性值。在这种情况下,\fItoken\fR 与对应于指定 \fBname\fR 属性的 \fBvalue\fR 属性的值相匹配。例如,以下搜索将查找分类为 "Development/Databases" 或 "System/Databases" 的软件包。请参见“示例”部分中查找 SMF 服务的示例。
+.sp
+.in +2
+.nf
+$ \fBpkg search info.classification:databases\fR
+.fi
+.in -2
+.sp
+
+结构化查询中缺少的字段使用隐式通配符。搜索 \fBbasename:pkg\fR 将会匹配 \fIindex\fR 为 \fBbasename\fR 且与 \fItoken\fR \fBpkg\fR 匹配的所有软件包中的所有操作,如以下部分输出中所示:
+.sp
+.in +2
+.nf
+$ \fBpkg search basename:pkg\fR
+INDEX    ACTION VALUE         PACKAGE
+basename dir    usr/share/pkg pkg:/package/[email protected]
+basename dir    var/sadm/pkg  pkg:/package/[email protected]
+basename dir    var/spool/pkg pkg:/package/[email protected]
+basename file   usr/bin/pkg   pkg:/package/[email protected]
+.fi
+.in -2
+.sp
+
+添加其他字段将会缩小搜索范围,如以下完整输出中所示:
+.sp
+.in +2
+.nf
+$ \fBpkg search file:basename:pkg\fR
+INDEX    ACTION VALUE       PACKAGE
+basename file   usr/bin/pkg pkg:/package/[email protected]
+.fi
+.in -2
+.sp
+
+\fIpkg_name\fR 和 \fItoken\fR 字段中支持显式通配符。\fIaction_name\fR 和 \fIindex\fR 必须完全匹配。
+.sp
+有关搜索文件和依赖项的示例,请参见“示例”部分。
+.sp
+要将操作转换为包含这些操作的软件包,请使用 \fB<>\fR,如以下部分输出中所示:
+.sp
+.in +2
+.nf
+$ \fBpkg search \e<pkg\e>\fR
+PACKAGE                                  PUBLISHER
+pkg:/package/[email protected]  solaris
+pkg:/package/[email protected] solaris
+.fi
+.in -2
+.sp
+
+使用 \fB-a\fR 选项(缺省设置)时,搜索 \fBtoken\fR 会导致返回与 \fBtoken\fR 匹配的操作的信息,而搜索 \fB<token>\fR 会导致返回一个软件包列表,这些软件包包含与 \fBtoken\fR 匹配的操作。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfix [\fB--accept\fR] [\fB--licenses\fR] [\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fBpkg verify\fR [\fB-Hqv\fR] [\fI pkg_fmri_pattern\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+验证当前映像中安装的所有软件包的安装情况。如果相关发布者的当前签名策略不是 \fBignore\fR,则会根据策略验证每个软件包的签名。有关如何应用签名策略的说明,请参见下文“映像属性”中的 \fBsignature-policy\fR。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
 .ad
 .sp .6
 .RS 4n
-修复 \fBpkg verify\fR 报告的任何错误。已安装软件包内容的验证基于自定义内容分析,该分析可能会返回与其他程序不同的结果。
-.sp
-使用 \fB--accept\fR 时,表示同意并接受所更新或安装的软件包的许可证条款。如果不提供此选项,且任何软件包许可证都要求接受,则操作将失败。
-.sp
-使用 \fB--licenses\fR 时,会在此操作过程中显示要安装或更新的软件包的所有许可证。
+仅验证当前映像中安装的指定软件包的安装情况。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在验证输出中省略标题。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrevert [\fB-nv\fR] [\fB--no-be-activate \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be \fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] (\fB--tagged\fR \fItag-name\fR ... | \fIpath-to-file\fR ...)\fR\fR
+\fB\fB-q\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果出现任何致命错误,则不显示任何信息,而是返回失败消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+包括有关软件包的信息性消息。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg fix\fR [\fB--accept\fR] [\fB--licenses\fR] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-将文件恢复为其交付时的状态。可以使用特定值标记所有文件,也可以恢复单个文件。文件所有权和保护也会得到恢复。
-.LP
-注意 - 
-.sp
-.RS 2
-将某些可编辑文件恢复为其缺省值可能会使系统无法引导,或导致其他故障。
+修复 \fBpkg verify\fR 报告的任何错误。已安装软件包内容的验证基于定制的内容分析,该分析可能会返回与其他程序不同的结果。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅修复 \fBpkg verify\fR 报告的有关当前映像中安装的指定软件包的错误。
 .RE
-对于其他所有选项,请参阅上面的 \fBinstall\fR 命令,以了解其用法及效果。
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--accept\fR\fR
+.ad
+.sp .6
+.RS 4n
+表示同意并接受所更新或安装的软件包的许可证条款。如果存在任何需要您接受的软件包许可证,而您未提供此选项,则操作将失败。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--licenses\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示在此操作过程中要安装或更新的软件包的所有许可证。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBmediator [\fB-aH\fR] [\fB-F\fR \fI format\fR] [\fImediator\fR ...]\fR\fR
+\fB\fBpkg revert\fR [\fB-nv\fR] [\fB- -no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] (\fB--tagged\fR \fI tag-name\fR ... | \fIpath-to-file\fR ...)\fR
 .ad
 .sp .6
 .RS 4n
-显示所有中介者的当前选定版本和/或实现;如果提供了参数,则仅显示指定中介者的当前选定版本和/或实现。
-.sp
-使用 \fB-a\fR 时,会列出可针对当前安装的软件包设置的中介。
-.sp
-使用 \fB-F\fR 时,会指定替代输出格式。当前,只有 \fBtsv\fR(Tab Separated Values,制表符分隔值)有效。
-.sp
-使用 \fB-H\fR,忽略列表的标题。
+将 \fBpkg\fR(5) 软件包提供的文件恢复为其交付时的状态。文件所有权和保护也会得到恢复。
+.LP
+注意 - 
+.sp
+.RS 2
+将某些可编辑文件恢复为其缺省值可能会使系统无法引导,或导致其他故障。
+.RE
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--tagged\fR \fItag-name\fR\fR
+.ad
+.sp .6
+.RS 4n
+恢复所有标记有 \fItag-name\fR 的文件。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpath-to-file\fR\fR
+.ad
+.sp .6
+.RS 4n
+恢复指定的文件。
+.RE
+
+对于其他所有选项,请参见上面的 \fBinstall\fR 命令。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-mediator [\fB-nv\fR] [\fB-I\fR \fI implementation\fR] [\fB-V\fR \fIversion\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI mediator\fR ...\fR\fR
+\fB\fBpkg mediator\fR [\fB-aH\fR] [\fB-F\fR \fIformat\fR] [\fImediator\fR ...] \fR
 .ad
 .sp .6
 .RS 4n
-设置当前映像中指定中介者的版本和/或实现。
-.sp
-使用 \fB-I\fR 时,会设置要使用的中介接口的实现。缺省情况下,如果未指定版本,则允许所有实现版本。要指定一个没有版本的实现,请附加 @ 符号。
-.sp
-使用 \fB-V\fR 时,会设置要使用的中介接口的版本。
-.sp
-如果指定的中介者版本和/或实现当前不可用,则会删除使用指定中介者的任何链接。
-.sp
-对于其他所有选项,请参阅上面的 \fBinstall\fR 命令,以了解其用法及效果。
+显示所有中介的当前选定版本和/或实现。
+.sp
+.ne 2
+.mk
+.na
+\fB\fImediator\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定中介的当前选定版本和/或实现。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunset-mediator [\fB-nvIV\fR] [\fB--no-be-activate \fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name\fR \fIname\fR] \fImediator \fR ...\fR\fR
+\fB\fB-a\fR\fR
+.ad
+.sp .6
+.RS 4n
+列出可为当前安装的软件包设置的中介。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR\fR
 .ad
 .sp .6
 .RS 4n
-将指定中介者的版本和/或实现恢复为系统缺省值。
-.sp
-使用 \fB-I\fR 时,仅恢复中介接口的实现。
-.sp
-使用 \fB-V\fR 时,仅恢复中介接口的版本。
-.sp
-对于其他所有选项,请参阅上面的 \fBinstall\fR 命令,以了解其用法及效果。
+指定备用输出格式。当前,只有 \fBtsv\fR(Tab Separated Values,制表符分隔值)有效。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBvariant [\fB-H\fR] [\fIvariant_spec \fR]\fR\fR
+\fB\fBpkg set-mediator\fR [\fB-nv\fR] [\fB-I\fR \fIimplementation\fR] [\fB-V\fR \fI version\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB- -require-backup-be\fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fImediator\fR ... \fR
+.ad
+.sp .6
+.RS 4n
+设置当前映像中指定中介的版本和/或实现。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR \fIimplementation\fR\fR
+.ad
+.sp .6
+.RS 4n
+设置要使用的中介接口的实现。缺省情况下,如果未指定版本,则允许所有实现版本。要指定一个没有版本的实现,请附加 @ 符号。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-v\fR \fIversion\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示所有变体的当前值;如果提供了参数,则仅显示指定变体的当前值。
-.sp
-使用 \fB-H\fR,忽略列表的标题。
+设置要使用的中介接口的版本。
+.RE
+
+如果指定的中介版本和/或实现当前不可用,则会删除使用指定中介的任何链接。
+.sp
+对于其他所有选项,请参见上面的 \fBinstall\fR 命令。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unset-mediator\fR [\fB-nvIV\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fImediator\fR ... \fR
+.ad
+.sp .6
+.RS 4n
+将指定中介的版本和/或实现恢复为系统缺省值。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅恢复中介接口的实现。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-V\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅恢复中介接口的版本。
+.RE
+
+对于其他所有选项,请参见上面的 \fBinstall\fR 命令。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBchange-variant [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI variant_spec\fR=\fIinstance\fR ...\fR\fR
+\fB\fBpkg variant\fR [\fB-H\fR] [\fB variant.\fR\fIvariant_name\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+显示在此映像中设置的所有变量的当前值。有关变量的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.sp
+.ne 2
+.mk
+.na
+\fB\fBvariant.\fR\fIvariant_name\fR\fR
 .ad
 .sp .6
 .RS 4n
-更改当前映像中的指定变体。
-.sp
-有关选项的用法和效果,请参阅上面的 \fBinstall\fR 命令。
+仅显示在此映像中设置的指定变量的当前值。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfacet [\fB-H\fR] [\fIfacet_spec\fR] \fR\fR
+\fB\fBpkg change-variant\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR |\fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIvariant_name\fR=\fI value\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-如果未提供参数,则显示所有侧面的当前值。如果提供了参数,则评估每个侧面将为 true 还是 false,并显示结果。
-.sp
-使用 \fB-H\fR,忽略列表的标题。
+更改在当前映像中设置的指定变量的值。
+.sp
+更改变量的值可能会导致删除、更新或安装某些软件包内容。更改变量值还可能会导致安装、更新或删除整个软件包,以满足新的映像配置。有关变量的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.sp
+有关选项的说明,请参见上述 \fBinstall\fR 命令。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBchange-facet [\fB-nvq\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [--no-backup-be | --require-backup-be] [--backup-be-name \fI name\fR] [\fB--deny-new-be\fR | \fB--require-new-be \fR] [\fB--be-name\fR \fIname\fR] \fI facet_spec\fR=[True|False|None] ...\fR\fR
+\fB\fBpkg facet\fR [\fB-H\fR] [\fI facet_name\fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+显示使用 \fBpkg change-facet\fR 命令在此映像中显式设置的所有侧面的当前值。有关侧面的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIfacet_name\fR\fR
 .ad
 .sp .6
 .RS 4n
-更改当前映像中的指定侧面。
-.sp
-可以将侧面设置为 \fBTrue\fR 或 \fBFalse\fR。将侧面设置为 \fBNone\fR 会从当前映像中删除该侧面的说明。
-.sp
-有关选项的用法和效果,请参阅上面的 \fBinstall\fR 命令。
+仅显示在此映像中设置的指定侧面的当前值。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBavoid [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg change-facet\fR [\fB-nvq\fR] [\fB-C\fR \fIn\fR] [\fB-g\fR \fI path_or_uri\fR ...] [\fB--accept\fR] [\fB--licenses\fR] [\fB--no-be-activate\fR] [\fB--no-backup-be\fR | \fB--require-backup-be \fR] [\fB--backup-be-name\fR \fIname\fR] [\fB--deny-new-be\fR | \fB--require-new-be\fR] [\fB--be-name \fR \fIname\fR] \fIfacet_name\fR=[\fB True\fR|\fBFalse\fR|\fBNone\fR] ...\fR
 .ad
 .sp .6
 .RS 4n
-如果指定的软件包是某个组依赖性的目标,则会通过将匹配指定模式的软件包名称放置在避免列表中,来避免安装这些软件包。只能避免安装当前尚未安装的软件包。如果某个软件包当前是某个组依赖性的目标,则卸载该软件包会将它放置在避免列表中。
-.sp
-如果不提供任何参数,则会显示每个避免安装的软件包,以及与该软件包存在组依赖性的任何软件包。
-.sp
-为满足所需的依赖性,会根据需要安装避免列表中的软件包。如果删除了该依赖性,则会卸载相应的软件包。
+更改当前映像中设置的指定侧面的值。
+.sp
+可以将侧面设置为 \fBTrue\fR 或 \fBFalse\fR。将侧面设置为 \fBNone\fR 时,系统会将缺省值 \fBTrue\fR 应用于该侧面;因此将安装任何由此侧面约束的操作。有关操作的信息,请参见 \fBpkg\fR(5) 手册页中的“操作”。
+.sp
+更改侧面的值可能会导致删除、更新或安装某些软件包内容。更改侧面值还可能会导致安装、更新或删除整个软件包,以满足新的映像配置。有关侧面的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.sp
+有关选项的说明,请参见上述 \fBinstall\fR 命令。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg avoid\fR [\fIpkg_fmri_pattern\fR ...] \fR
+.ad
+.sp .6
+.RS 4n
+显示每个避免安装的软件包,以及对该软件包存在组依赖性的任何软件包。
+.sp
+如果需要满足 require 依赖性,则会安装避免列表中的软件包。如果删除了该依赖性,则会卸载相应的软件包。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果指定的软件包是某个组依赖性的目标,则会通过将匹配指定模式的软件包名称放置在避免列表中来避免安装这些软件包。只能避免安装当前尚未安装的软件包。如果某个软件包当前是某个组依赖性的目标,则卸载该软件包会将它放置在避免列表中。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunavoid [\fIpkg_fmri_pattern\fR ...] \fR\fR
+\fB\fBpkg unavoid\fR [\fIpkg_fmri_pattern \fR ...]\fR
+.ad
+.sp .6
+.RS 4n
+显示避免安装的软件包的列表。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
 .ad
 .sp .6
 .RS 4n
-从避免列表中删除指定的软件包。使用此子命令无法删除避免列表中与某个已安装软件包的组依赖性相匹配的软件包。要从避免列表中删除与某个组依赖性匹配的某个软件包,请安装该软件包。
-.sp
-如果不提供任何参数,则会显示已避免安装的软件包的列表。
+从避免列表中删除指定的软件包。使用此子命令无法删除避免列表中与某个已安装软件包的组依赖性相匹配的软件包。要从避免列表中删除与某个组依赖性相匹配的软件包,请安装该软件包。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg freeze\fR [\fB-n\fR] [\fB-c \fR \fIreason\fR] [\fIpkg_fmri_pattern\fR] ...\fR
+.ad
+.sp .6
+.RS 4n
+显示有关当前已冻结软件包的信息:软件包名称、版本、软件包冻结时间以及任何冻结软件包的相关原因。
+.sp
+冻结某个软件包不会阻止删除该软件包。删除软件包时不会显示警告。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的软件包冻结到指定的版本。如果未提供版本,则必须安装该软件包,然后将它冻结在该已安装版本。冻结一个已经冻结的软件包会将冻结版本替换为新指定的版本。
+.sp
+如果安装或更新冻结的软件包,则其最终版本必须与冻结时使用的版本匹配。例如,如果某个软件包在冻结时的版本为 1.2,则可以将它更新到 1.2.1、1.2.9、1.2.0.0.1,等等。但该软件包的最终版本不能为 1.3 或 1.1。\fIpkg_fmri_pattern\fR 中提供的发布者用于查找匹配的软件包。但是,在冻结过程中不会记录发布者信息。软件包只针对其版本(而不是发布者)进行冻结。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBfreeze [\fB-n\fR] [\fB-c\fR \fI reason\fR] [\fIpkg_fmri_pattern\fR] ...\fR\fR
+\fB\fB-c\fR \fIreason\fR\fR
+.ad
+.sp .6
+.RS 4n
+记录冻结软件包的 \fI原因\fR。当安装或更新因冻结而不能继续进行时,将会显示该原因。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
 .ad
 .sp .6
 .RS 4n
-将指定的软件包冻结到指定的版本。如果未提供版本,则必须安装该软件包,然后将它冻结在该已安装版本。如果冻结的软件包已安装或已更新,则它最终使用的版本必须与冻结时使用的版本匹配。例如,如果某个软件包在冻结时的版本为 1.2,则可以将它更新到 1.2.1、1.2.9、1.2.0.0.1,等等。该软件包最终使用的版本不能是 1.3 或 1.1。\fIpkg_fmri_pattern\fR 中提供的发布者用于查找匹配软件包。但是,在冻结过程中不会记录发布者信息。软件包只能针对其版本(而不能是发布者)进行冻结。冻结一个已经冻结的软件包会将冻结版本替换为新指定的版本。
-.sp
-如果未提供任何软件包,则会显示有关当前已冻结软件包的信息:软件包名称、版本、冻结时间以及任何相关原因。
-.sp
-冻结某个软件包不会阻止删除该软件包。删除软件包时不会显示警告。
-.sp
-使用 \fB-c\fR 时,会记录冻结软件包的 \fIreason\fR。当冻结操作阻止安装或更新成功进行时,将会显示原因。
-.sp
-使用 \fB-n\fR 时,会试运行操作,并显示要冻结的软件包的列表,但不冻结任何软件包。
+试运行冻结操作,并显示要冻结的软件包的列表,但不冻结任何软件包。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unfreeze\fR [\fB-n\fR] [\fI pkg_name_pattern\fR] ...\fR
+.ad
+.sp .6
+.RS 4n
+显示有关当前已冻结软件包的信息:软件包名称、版本、软件包冻结时间以及任何冻结软件包的相关原因。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpkg_fmri_pattern\fR\fR
+.ad
+.sp .6
+.RS 4n
+从指定的软件包中删除冻结操作施加的约束。将会忽略提供的版本。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunfreeze [\fB-n\fR] [\fIpkg_name_pattern \fR] ...\fR\fR
+\fB\fB-n\fR\fR
 .ad
 .sp .6
 .RS 4n
-从指定的软件包中删除冻结操作强加的约束。将会忽略提供的任何版本。
-.sp
-使用 \fB-n\fR 时,会试运行解冻,并显示要解冻的软件包的列表,但不解冻任何软件包。
+试运行解冻操作,并显示要解冻的软件包的列表,但不解冻任何软件包。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBproperty [\fB-H\fR] [\fIpropname \fR ...]\fR\fR
+\fB\fBpkg property\fR [\fB-H\fR] [\fI propname\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
-显示映像属性信息。如果不提供参数,则会显示所有映像属性的名称和值。如果请求了特定的属性名称列表,则显示这些属性的名称和值。
-.sp
-使用 \fB-H\fR 时,会省略列表中的标题。
+显示所有映像属性的名称和值。有关映像属性的说明,请参见下面的“映像属性”。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpropname\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定属性的名称和值。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-property \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-property\fR \fIpropname\fR \fI propvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -891,7 +1821,7 @@
 .ne 2
 .mk
 .na
-\fB\fBadd-property-value \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fBpkg add-property-value\fR \fIpropname \fR \fIpropvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -902,7 +1832,7 @@
 .ne 2
 .mk
 .na
-\fB\fBremove-property-value \fIpropname\fR \fI propvalue\fR\fR\fR
+\fB\fBpkg remove-property-value\fR \fIpropname \fR \fIpropvalue\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -913,7 +1843,7 @@
 .ne 2
 .mk
 .na
-\fB\fBunset-property \fIpropname\fR ... \fR\fR
+\fB\fBpkg unset-property\fR \fIpropname\fR ... \fR
 .ad
 .sp .6
 .RS 4n
@@ -924,110 +1854,473 @@
 .ne 2
 .mk
 .na
-\fB\fBpublisher [\fB-HPn\fR] [\fIpublisher \fR ...]\fR\fR
+\fB\fBpkg publisher\fR [\fB-HPn\fR] [\fB-F\fR \fIformat\fR] [\fIpublisher\fR ...] \fR
+.ad
+.sp .6
+.RS 4n
+按搜索优先顺序显示所有发布者、其源 URI 和镜像的列表。
+.sp
+.ne 2
+.mk
+.na
+\fB\fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定发布者的详细配置信息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示发布者搜索顺序中的第一个发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示已启用的发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-F\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定备用输出格式。当前,只有 \fBtsv\fR(Tab Separated Values,制表符分隔值)有效。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-publisher\fR [\fB-Ped\fR] [\fB-k\fR \fIssl_key\fR] [\fB-c\fR \fI ssl_cert\fR] [\fB-g\fR \fIorigin_to_add\fR | \fB- -add-origin\fR \fIorigin_to_add\fR ...] [\fB-G\fR \fI origin_to_remove\fR | \fB--remove-origin\fR \fIorigin_to_remove \fR ...] [\fB-m\fR \fImirror_to_add\fR | \fB- -add-mirror\fR \fImirror_to_add\fR ...] [\fB-M\fR \fI mirror_to_remove\fR | \fB--remove-mirror\fR \fImirror_to_remove \fR ...] [\fB--enable\fR] [\fB--disable\fR] [\fB--no-refresh\fR] [\fB--reset-uuid\fR] [\fB--non-sticky \fR] [\fB--sticky\fR] [\fB--search-after\fR \fI publisher\fR] [\fB--search-before\fR \fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR \fI path_to_CA\fR] [\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--set-property\fR \fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR \fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR \fIname_of_property_to_delete \fR] [\fB--proxy\fR \fIproxy_to_use\fR] \fI publisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+更新现有发布者,或添加发布者。如果未指定任何影响搜索顺序的选项,则会将新发布者附加到搜索顺序,因此,会最后搜索这些新发布者。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.br
+.na
+\fB\fB--search-first\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的发布者设置为搜索顺序中第一个。安装新软件包时,将首先搜索此发布者。对已安装软件包的更新将来自最初提供该软件包的同一发布者,前提是该发布者保持粘滞。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--non-sticky\fR\fR
+.ad
+.sp .6
+.RS 4n
+对于最初从此发布者安装的软件包,更新可以从级别比此发布者更高的发布者处获取。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--sticky\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示发布者信息。如果不提供参数,则会按搜索优先顺序显示所有发布者、其源 URI 和镜像的列表。如果请求了特定的发布者,则显示这些发布者的详细配置。
-.sp
-使用 \fB-H\fR 时,会省略列表中的标题。
-.sp
-使用 \fB-P\fR 时,仅按发布者搜索顺序显示第一个发布者。
-.sp
-使用 \fB-n\fR 时,仅显示已启用的发布者。
+对于从此发布者安装的软件包,更新必须也来自此发布者。这是缺省行为。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--search-before\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+更改发布者搜索顺序,以便在此选项中指定的发布者之前搜索添加或修改的发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--search-after\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+更改发布者搜索顺序,以便在此选项中指定的发布者之后搜索添加或修改的发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--approve-ca-cert\fR \fIpath_to_CA\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的证书添加为可信的 CA 证书。\fBpkg publisher\fR 命令的详细输出中列出了用户批准的 CA 证书的 PEM 表示形式中的散列。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR\fR
+.ad
+.sp .6
+.RS 4n
+将其 PEM 表示形式具有给定散列的证书视为已撤销。\fBpkg publisher\fR 命令的详细输出中列出了用户撤销的 CA 证书的散列。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR\fR
+.ad
+.sp .6
+.RS 4n
+从已批准证书列表和已撤销证书列表中删除具有给定散列的证书。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--set-property\fR \fIname_of_property\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+更新现有发布者属性或添加新的发布者属性。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+向现有发布者属性添加值,或添加新的发布者属性。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--remove-property-value\fR \fIname_of_property \fR=\fIvalue_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+从现有发布者属性中删除值。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--unset-property\fR \fIname_of_property_to_delete \fR\fR
+.ad
+.sp .6
+.RS 4n
+删除现有的发布者属性。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定客户机 SSL 密钥。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定客户机 SSL 证书。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset-publisher [\fB-Ped\fR] [\fB-k\fR\fI ssl_key\fR] [\fB-c\fR\fIssl_cert\fR] [\fB-g\fR\fIorigin_to_add\fR | \fB--add-origin \fR\fIorigin_to_add\fR ...][\fB-G\fR\fI origin_to_remove\fR | \fB--remove-origin\fR\fIorigin_to_remove \fR ...][\fB-m\fR\fImirror_to_add\fR | \fB- -add-mirror\fR\fImirror_to_add\fR ...][\fB-M\fR\fI mirror_to_remove\fR | \fB--remove-mirror\fR\fImirror_to_remove \fR ...][\fB-p\fR\fIrepo_uri\fR] [\fB--enable\fR] [\fB--disable\fR] [\fB--no-refresh\fR] [\fB--reset-uuid\fR] [\fB--non-sticky\fR] [\fB--sticky\fR] [\fB--search-after\fR\fIpublisher\fR] [\fB--search-before \fR\fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR\fIpath_to_CA\fR] [\fB--revoke-ca-cert\fR\fIhash_of_CA_to_remove\fR] [\fB--unset-ca-cert\fR\fIhash_of_CA_to_remove\fR] [\fB--set-property\fR\fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR\fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR\fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR\fIname_of_property_to_delete \fR] [\fIpublisher\fR]\fR\fR
+\fB\fB-g\fR \fIorigin_to_add\fR\fR
+.ad
+.br
+.na
+\fB\fB--add-origin\fR \fIorigin_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的 URI 或路径添加为给定发布者的源。这应该是软件包系统信息库或归档的位置。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-G\fR \fIorigin_to_remove\fR\fR
+.ad
+.br
+.na
+\fB\fB--remove-origin\fR \fIorigin_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+从给定发布者的源列表中删除 URI 或路径。可以使用特殊值 \fB*\fR 来删除所有源。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+不尝试联系映像发布者的系统信息库来检索最新的可用软件包列表和其他元数据。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--reset-uuid\fR\fR
 .ad
 .sp .6
 .RS 4n
-更新现有发布者,或添加软件包发布者。如果未指定任何影响搜索顺序的选项,则会将新发布者附加到搜索顺序,因此,会最后搜索这些新发布者。
-.sp
-使用 \fB-P\fR 或 \fB--search-first\fR 时,会将指定的发布者设置在搜索顺序的首位。安装新软件包时,将首先搜索此发布者。对已安装软件包的更新将来自最初提供该软件包的同一发布者,前提是该发布者保持粘滞。将 \fB-P\fR 或 \fB--search-first\fR 与 \fB-p\fR 一起使用时,仅将添加的发布者放置在搜索顺序的首位。
-.sp
-使用 \fB--non-sticky\fR 时,会指定级别比此发布者更高的发布者可以为最初通过此发布者安装的软件包提供更新。
-.sp
-使用 \fB--sticky\fR 时,会指定对通过此发布者安装的软件包的更新必须也来自此发布者。这是缺省行为。
-.sp
-使用 \fB--search-before\fR 时,会更改发布者搜索顺序,以便在指定的发布者之前搜索被修改的发布者。与 \fB-p\fR 一起使用时,\fB--search-before\fR 仅适用于添加的发布者。
-.sp
-使用 \fB--search-after\fR 时,会更改发布者搜索顺序,以便在指定的发布者之后搜索被修改的发布者。与 \fB-p\fR 一起使用时,\fB--search-after\fR 仅适用于添加的发布者。
-.sp
-使用 \fB--approve-ca-cert\fR 时,会将给定的证书添加为可信的 CA 证书。\fBpkg publisher\fR 命令的详细输出中列出了用户批准的 CA 证书的 PEM 表示法散列。
-.sp
-使用 \fB--revoke-ca-cert\fR 时,会将具有其 PEM 表示法的给定散列的证书视为已撤销。\fBpkg publisher\fR 命令的详细输出中列出了用户撤销的 CA 证书的散列。
-.sp
-使用 \fB--unset-ca-cert\fR 时,会从已批准证书列表和已撤销证书列表中删除具有给定散列的证书。
-.sp
-使用 \fB--set-property\fR 时,会更新现有的发布者属性,或添加新的发布者属性。
-.sp
-使用 \fB--add-property-value\fR 时,会向现有的发布者属性添加值,或添加新的发布者属性。
-.sp
-使用 \fB--remove-property-value\fR 时,会从现有的发布者属性中删除某个值。
-.sp
-使用 \fB--unset-property\fR 时,会删除某个现有的发布者属性。
-.sp
-使用 \fB-c\fR 和 \fB-k\fR 时,会分别指定客户端 SSL 证书和密钥。
-.sp
-使用 \fB-g\fR (\fB--add-origin\fR) 时,会将指定的 URI 或路径添加为给定发布者的源。这应该是软件包系统信息库或归档的位置。
-.sp
-使用 \fB-G\fR (\fB--remove-origin\fR) 时,会从给定发布者的源列表中删除 URI 或路径。可以使用特殊值 \fB*\fR 来删除所有源。
-.sp
-使用 \fB--no-refresh\fR 时,不会尝试联系系统信息库来让映像发布者检索最新的可用软件包列表和其他元数据。
-.sp
-使用 \fB--reset-uuid\fR 时,会选择一个新的唯一标识符,用于向其发布者标识此映像。
-.sp
-使用 \fB-m\fR (\fB--add-mirror\fR) 时,会将 URI 添加为给定发布者的镜像。
-.sp
-使用 \fB-M\fR (\fB--remove-mirror\fR) 时,会从给定发布者的镜像列表中删除 URI。可以使用特殊值 \fB*\fR 来删除所有镜像。
-.sp
-使用 \fB-p\fR 时,会从指定的系统信息库 URI 中检索发布者配置信息。如果指定了发布者,则仅添加或更新匹配的发布者。如果未指定发布者,则根据需要添加或更新所有发布者。此选项不能与 \fB-g\fR、\fB--add-origin\fR、\fB--G\fR、\fB--remove-origin\fR、\fB-m\fR、\fB--add-mirror\fR、\fB-M\fR、\fB--remove-mirror\fR、\fB--disable\fR、\fB--enable\fR、\fB--no-refresh\fR 或 \fB--reset-uuid\fR 选项结合使用。
-.sp
-使用 \fB-e\fR (\fB--enable\fR) 时,会启用发布者。使用 \fB-d\fR (\fB--disable\fR) 时,会禁用发布者。填充软件包列表时,或者执行某些软件包操作(安装、卸载和更新)时,将不使用被禁用的发布者。但是,仍可以设置和查看被禁用的发布者的属性。如果只存在一个发布者,则不能将其禁用。
+选择一个新的唯一标识符,用于向其发布者标识此映像。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR \fImirror_to_add\fR\fR
+.ad
+.br
+.na
+\fB\fB--add-mirror\fR \fImirror_to_add\fR\fR
+.ad
+.sp .6
+.RS 4n
+将 URI 添加为给定发布者的镜像。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-M\fR \fImirror_to_remove\fR\fR
+.ad
+.br
+.na
+\fB\fB--remove-mirror\fR \fImirror_to_remove\fR\fR
+.ad
+.sp .6
+.RS 4n
+从给定发布者的镜像列表中删除 URI。可以使用特殊值 \fB*\fR 来删除所有镜像。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-e\fR\fR
+.ad
+.br
+.na
+\fB\fB--enable\fR\fR
+.ad
+.sp .6
+.RS 4n
+启用发布者。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-d\fR\fR
+.ad
+.br
+.na
+\fB\fB--disable\fR\fR
+.ad
+.sp .6
+.RS 4n
+禁用发布者。填充软件包列表时,或者执行某些软件包操作(安装、卸载和更新)时,将不使用被禁用的发布者。但是,仍可以设置和查看被禁用的发布者的属性。如果只存在一个发布者,则不能将其禁用。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBunset-publisher \fIpublisher\fR ... \fR\fR
+\fB\fB--proxy\fR \fIproxy_to_use\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用指定的 Web 代理 URI 检索指定源 (\fB-g\fR) 或镜像 (\fB-m\fR) 的内容。代理值存储在发布者配置中。在运行时,\fB$http_proxy\fR 或相关环境变量会覆盖此代理设置。有关接受的环境变量名列表,请参见 \fBcurl\fR(1) 手册页。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg set-publisher\fR \fB-p\fR \fI repo_uri\fR [\fB-Ped\fR] [\fB-k\fR \fIssl_key \fR] [\fB-c\fR \fIssl_cert\fR] [\fB- -non-sticky\fR] [\fB--sticky\fR] [\fB--search-after\fR \fI publisher\fR] [\fB--search-before\fR \fIpublisher\fR] [\fB--search-first\fR] [\fB--approve-ca-cert\fR \fI path_to_CA\fR] [\fB--revoke-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--unset-ca-cert\fR \fIhash_of_CA_to_remove \fR] [\fB--set-property\fR \fIname_of_property\fR=\fI value\fR] [\fB--add-property-value\fR \fIname_of_property \fR=\fIvalue_to_add\fR] [\fB--remove-property-value \fR \fIname_of_property\fR=\fIvalue_to_remove \fR] [\fB--unset-property\fR \fIname_of_property_to_delete \fR] [\fB--proxy\fR \fIproxy_to_use\fR] [\fIpublisher\fR]\fR
 .ad
 .sp .6
 .RS 4n
-删除与一个或多个给定发布者相关联的配置。
+从 \fIrepo_uri\fR 系统信息库 URI 中检索发布者配置信息。
+.sp
+如果为此 \fBset-publisher\fR 子命令指定了发布者操作数,则仅添加或更新该发布者。如果未指定发布者,则相应添加或更新 \fIrepo_uri\fR 中的所有发布者。
+.sp
+有关选项的说明,请参见上述 \fBset-publisher\fR 命令。与 \fB-p\fR 一起使用时,\fB-P\fR、\fB--search-first\fR、\fB--search-before\fR 以及 \fB--search-after\fR 选项仅适用于添加的发布者,而不适用于更新的发布者。
+.sp
+\fB-p\fR 选项不能与以下选项结合使用:\fB-g\fR、\fB--add-origin\fR、\fB-G\fR、\fB--remove-origin\fR、\fB-m\fR、\fB--add-mirror\fR、\fB-M\fR、\fB--remove-mirror\fR、\fB--disable\fR、\fB--enable\fR、\fB--no-refresh\fR 或 \fB--reset-uuid\fR。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg unset-publisher\fR \fIpublisher \fR ...\fR
+.ad
+.sp .6
+.RS 4n
+删除与一个或多个指定发布者相关联的配置。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg history\fR [\fB-HNl\fR] [\fB-t\fR [\fItime\fR | \fItime\fR-\fI time\fR],...] [\fB-o\fR \fIcolumn\fR,...] [\fB-n\fR \fInumber\fR]\fR
+.ad
+.sp .6
+.RS 4n
+显示适用映像的命令历史记录。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBhistory [\fB-Hl\fR] [\fB-t\fR [\fI time\fR | \fItime\fR-\fItime\fR],...][\fB-o\fR\fIcolumn\fR,...][\fB-n\fR\fI number\fR]\fR\fR
+\fB\fB-t\fR \fItime\fR\fR
+.ad
+.br
+.na
+\fB\fB-t\fR \fItime\fR-\fItime\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示以逗号分隔列表指定的时间戳(格式为 \fB%Y-%m-%dT%H:%M:%S\fR)对应的日志记录(请参见 \fBstrftime\fR(3C))。要指定时间范围,请在开始和完成时间戳之间使用连字符 (-)。可以将关键字 \fBnow\fR 用作当前时间的别名。如果指定的时间戳包含重复的时间戳或重叠的日期范围,则每个重复的历史记录事件仅显示一次。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-l\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示适用映像的命令历史记录。
-.sp
-使用 \fB-H\fR 时,会省略列表中的标题。
-.sp
-使用 \fB-t\fR 时,会显示时间戳(格式为 \fB%Y-%m-%dT%H:%M:%S\fR)逗号分隔列表的日志记录(请参见 \fBstrftime\fR(3C))。要指定时间范围,请在开始和完成时间戳之间使用连字符 (-)。可以将关键字 \fBnow\fR 用作当前时间的别名。如果指定的时间戳包含重复的时间戳或重叠的日期范围,则仅显示每个重复历史记录事件的单个实例。
-.sp
-使用 \fB-l\fR 时,会以长格式显示日志记录,也就是说,除了显示标准格式的内容外,还包括命令的结果、命令完成时间、所用客户端的版本和名称、执行操作的用户名,以及执行命令时遇到的任何错误。
-.sp
-使用 \fB-n\fR 时,仅显示指定数目的最近条目。
-.sp
-使用 \fB-o\fR 时,会使用指定的列名逗号分隔列表显示输出。有效的列名为:
+以长格式显示日志记录,也就是说,除了显示标准格式的内容外,还包括命令的结果、命令完成时间、所用客户机的版本和名称、执行操作的用户名,以及执行命令时遇到的任何错误。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-N\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示发行说明文本。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-n\fR \fInumber\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定数目的最近条目。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR \fIcolumn\fR\fR
+.ad
+.sp .6
+.RS 4n
+按照以逗号分隔的指定列名列表显示输出。有效的列名为:
 .sp
 .ne 2
 .mk
 .na
 \fB\fBbe\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 在其上启动此操作的引导环境的名称。
 .RE
 
@@ -1037,8 +2330,8 @@
 .na
 \fB\fBbe_uuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 在其上启动此操作的引导环境的 \fBuuid\fR。
 .RE
 
@@ -1048,8 +2341,8 @@
 .na
 \fB\fBclient\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 客户端的名称。
 .RE
 
@@ -1059,8 +2352,8 @@
 .na
 \fB\fBclient_ver\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 客户端的版本。
 .RE
 
@@ -1070,8 +2363,8 @@
 .na
 \fB\fBcommand\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用于此操作的命令行。
 .RE
 
@@ -1081,8 +2374,8 @@
 .na
 \fB\fBfinish\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 完成此操作时的时间。
 .RE
 
@@ -1092,8 +2385,8 @@
 .na
 \fB\fBid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 启动此操作的用户 ID。
 .RE
 
@@ -1103,8 +2396,8 @@
 .na
 \fB\fBnew_be\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此操作创建的新引导环境。
 .RE
 
@@ -1114,8 +2407,8 @@
 .na
 \fB\fBnew_be_uuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此操作创建的新引导环境的 \fBuuid\fR。
 .RE
 
@@ -1125,8 +2418,8 @@
 .na
 \fB\fBoperation\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 操作的名称。
 .RE
 
@@ -1136,8 +2429,8 @@
 .na
 \fB\fBoutcome\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此操作的结果摘要。
 .RE
 
@@ -1147,8 +2440,8 @@
 .na
 \fB\fBreason\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 有关此操作的结果的其他信息。
 .RE
 
@@ -1156,10 +2449,21 @@
 .ne 2
 .mk
 .na
+\fB\fBrelease_note\fR\fR
+.ad
+.sp .6
+.RS 4n
+指示此操作是否已生成发行说明。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBsnapshot\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 执行此操作期间创建的快照。仅当成功完成操作后未自动删除快照时,才会记录此信息。
 .RE
 
@@ -1169,8 +2473,8 @@
 .na
 \fB\fBstart\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 启动此操作时的时间。
 .RE
 
@@ -1180,9 +2484,9 @@
 .na
 \fB\fBtime\fR\fR
 .ad
-.RS 15n
-.rt  
-执行此操作花费的总时间。(对于花费时间不到一秒的操作,将显示 0:00:00)。
+.sp .6
+.RS 4n
+执行此操作花费的总时间。对于用时不到一秒的操作,将显示 0:00:00。
 .RE
 
 .sp
@@ -1191,8 +2495,8 @@
 .na
 \fB\fBuser\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 启动此操作的用户名。
 .RE
 
@@ -1203,11 +2507,13 @@
 可通过使用 \fBbe_uuid\fR 或 \fBnew_be_uuid\fR 字段查找当前引导环境名称,来获取 \fBbe\fR 和 \fBnew_be\fR 的值。如果某个引导环境后来已重命名,随后又被删除,则显示的 \fBbe\fR 和 \fBnew_be\fR 值是执行 \fBpkg\fR 操作时记录的值。
 .RE
 
+.RE
+
 .sp
 .ne 2
 .mk
 .na
-\fB\fBpurge-history\fR\fR
+\fB\fBpkg purge-history\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1218,7 +2524,7 @@
 .ne 2
 .mk
 .na
-\fB\fBrebuild-index\fR\fR
+\fB\fBpkg rebuild-index\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1229,7 +2535,7 @@
 .ne 2
 .mk
 .na
-\fB\fBupdate-format\fR\fR
+\fB\fBpkg update-format\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -1240,42 +2546,104 @@
 .ne 2
 .mk
 .na
-\fB\fBversion\fR\fR
+\fB\fBpkg version\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示一个用于标识 \fBpkg\fR(1) 版本的唯一字符串。不保证在不同版本中,此字符串在任何方面都具有类似性。
+显示一个用于唯一标识 \fBpkg\fR 版本的字符串。不保证在不同版本中,此字符串在任何方面都具有类似性。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkg help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBimage-create [\fB-FPUfz\fR] [\fB--force \fR] [\fB--full\fR | \fB--partial\fR | \fB--user\fR] [\fB--zone\fR] [\fB-k\fR\fIssl_key\fR] [\fB-c\fR\fIssl_cert\fR] [\fB--no-refresh\fR] [\fB--variant\fR\fIvariant_spec\fR=\fIinstance \fR ...][\fB-g\fR\fIpath_or_uri\fR | \fB- -origin\fR\fIpath_or_uri\fR ...][\fB-m\fR\fI uri\fR | \fB--mirror\fR\fIuri\fR ...][\fB--facet\fR\fIfacet_spec\fR=(True|False) ...][(\fB-p\fR | \fB--publisher\fR) [\fIname\fR=]\fI repo_uri\fR] \fIdir\fR\fR\fR
+\fB\fBpkg image-create\fR [\fB-FPUz\fR] [\fB-f\fR |\fB--force\fR] [\fB--full\fR | \fB--partial \fR | \fB--user\fR] [\fB--zone\fR] [\fB-k\fR \fI ssl_key\fR] [\fB-c\fR \fIssl_cert\fR] [\fB--no-refresh\fR] [\fB--variant\fR \fIvariant_name \fR=\fIvalue\fR ...] [\fB-g\fR \fI path_or_uri\fR | \fB--origin\fR \fIpath_or_uri\fR ...] [\fB-m\fR \fIuri\fR | \fB--mirror\fR \fI uri\fR ...] [\fB--set-property\fR \fIname_of_property \fR=\fIvalue\fR] [\fB--facet\fR \fI facet_name\fR=(\fBTrue\fR|\fBFalse\fR) ...] [(\fB-p\fR | \fB--publisher\fR) [\fIname\fR=]\fI repo_uri\fR] \fIdir\fR\fR
 .ad
 .sp .6
 .RS 4n
-在 \fIdir\fR 指定的位置,创建一个适合于软件包操作的映像。缺省的映像类型为"用户",即 \fB-U\fR (\fB--user\fR) 选项指定的类型。可以将映像类型设置为完整映像(\fB--F\fR 或 \fB--full\fR),或者设置为与完整映像(包括给定的 \fIdir\fR 路径)链接的部分映像(\fB-P\fR 或 \fB--partial\fR)。可以使用 \fB-g\fR 或 \fB--origin\fR 指定其他源。可以使用 \fB--m\fR 或 \fB--mirror\fR 指定其他镜像。
+在 \fIdir\fR 指定的位置,创建一个适合于软件包操作的映像。缺省的映像类型为“用户”,即 \fB-U\fR (\fB--user\fR) 选项指定的类型。可以将映像类型设置为完整映像(\fB--F\fR 或 \fB--full\fR),或者设置为与完整映像(包括给定的 \fIdir\fR 路径)链接的部分映像(\fB-P\fR 或 \fB--partial\fR)。可以使用 \fB-g\fR 或 \fB--origin\fR 指定其他源。可以使用 \fB-m\fR 或 \fB--mirror\fR 指定其他镜像。
 .sp
 必须使用 \fB-p\fR 或 \fB--publisher\fR 选项提供软件包系统信息库 URI。如果还提供了某个发布者名称,则创建映像时仅添加该发布者。如果未提供发布者名称,则会将指定的系统信息库已知的所有发布者添加到映像。完成初始创建操作后,将会尝试检索与此发布者关联的目录。
 .sp
 对于使用客户端 SSL 验证的发布者,可以通过 \fB-c\fR 和 \fB-k\fR 选项注册客户端密钥和客户端证书。此密钥和证书用于映像创建期间添加的所有发布者。
 .sp
-如果要在非全局区域上下文中运行映像,则可以使用 \fB-z\fR (\fB--zone\fR) 选项设置相应的变体。
-.sp
-使用 \fB-f\fR (\fB--force\fR) 时,会基于现有映像强制创建一个映像。请慎用此选项。
-.sp
-使用 \fB--no-refresh\fR 时,不会尝试联系系统信息库来让映像发布者检索最新的可用软件包列表和其他元数据。
-.sp
-使用 \fB--variant\fR 时,会将指定的变体设置为指示值。
-.sp
-使用 \fB--facet\fR 时,会将指定的侧面设置为指示值。
+如果要在非全局区域上下文中运行映像,则可以使用 \fB-z\fR (\fB--zone\fR) 选项设置相应的变量。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-f\fR\fR
+.ad
+.br
+.na
+\fB\fB--force\fR\fR
+.ad
+.sp .6
+.RS 4n
+基于现有映像强制创建一个映像。请慎用此选项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-refresh\fR\fR
+.ad
+.sp .6
+.RS 4n
+不尝试联系映像发布者的系统信息库来检索最新的可用软件包列表和其他元数据。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--variant\fR \fIvariant_name\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的变量设置为指示值。有关变量的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--facet\fR \fIfacet_name\fR=(\fB True\fR|\fBFalse\fR)\fR
+.ad
+.sp .6
+.RS 4n
+将指定的侧面设置为指示值。有关侧面的更多信息,请参见 \fBpkg\fR(5) 手册页中的“侧面和变量”。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--set-property\fR \fIname_of_property\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的映像属性设置为指示值。有关映像属性的说明,请参见下面的“映像属性”。
+.RE
+
 .RE
 
 .SH 映像属性
 .sp
 .LP
-以下属性是映像的一部分,可使用 \fBset-property\fR 子命令进行设置。使用 \fBproperty\fR 子命令可以查看这些属性的值。
+以下属性可定义映像的特征。这些属性存储有关映像的用途、内容和行为的信息。要查看映像中这些属性的当前值,请使用 \fBpkg property\fR 命令。要修改这些属性的值,请使用 \fBpkg set-property\fR 和 \fBpkg unset-property\fR 命令。
 .sp
 .ne 2
 .mk
@@ -1291,9 +2659,9 @@
 .na
 \fB\fBdefault\fR\fR
 .ad
-.RS 14n
-.rt  
-应用缺省 BE 创建策略 \fBcreate-backup\fR。
+.sp .6
+.RS 4n
+应用缺省引导环境创建策略 \fBcreate-backup\fR。
 .RE
 
 .sp
@@ -1302,9 +2670,9 @@
 .na
 \fB\fBalways-new\fR\fR
 .ad
-.RS 14n
-.rt  
-所有软件包操作均需要重新引导:在下次引导时在设为活动状态的新 BE 中执行这些操作。除非显式请求,否则不会创建备份 BE。
+.sp .6
+.RS 4n
+所有软件包操作均需要重新引导:在下次引导时设为活动状态的新引导环境中执行这些操作。除非显式请求,否则不创建备份引导环境。
 .sp
 该策略最为安全,但是它比大多数站点的需要更为严格,因为在不重新引导的情况下无法添加任何软件包。
 .RE
@@ -1319,9 +2687,9 @@
 .ad
 .sp .6
 .RS 4n
-对于需要重新引导的软件包操作,在下一次引导时,将创建一个新的 BE 并将其设置为处于活动状态。如果修改了软件包或安装了可能影响内核的内容,并且该操作影响实时 BE,将创建备份 BE,但不会将其设置为活动状态。也可以显式请求备份 BE。
-.sp
-仅当新安装的软件导致系统不稳定时(有可能发生,但比较少见),该策略才具有潜在风险。
+对于需要重新引导的软件包操作,在下一次引导时,将创建一个新的引导环境并将其设置为活动状态。如果修改了软件包或安装了可能影响内核的内容,并且该操作影响实时引导环境,将创建备份引导环境,但不会将其设置为活动状态。也可以显式请求创建备份引导环境。
+.sp
+仅当新安装的软件导致系统不稳定时(有可能发生,但比较少见),该策略才可能存在风险。
 .RE
 
 .sp
@@ -1332,9 +2700,9 @@
 .ad
 .sp .6
 .RS 4n
-对于需要重新引导的软件包操作,在下一次引导时,将创建一个新的 BE 并将其设置为处于活动状态。除非显式请求,否则不会创建备份 BE。
-.sp
-该策略的风险性最高,因为如果对实时 BE 的打包更改使得以后不可再进行更改,则可能没有可回退到的最近 BE。
+对于需要重新引导的软件包操作,在下一次引导时,将创建一个新的引导环境并将其设置为活动状态。除非显式请求,否则不创建备份引导环境。
+.sp
+该策略的风险最高,因为如果对实时引导环境的打包更改使得以后无法再进行更改,则可能没有可回退的最近引导环境。
 .RE
 
 .sp
@@ -1358,7 +2726,7 @@
 .ad
 .sp .6
 .RS 4n
-(字符串)如果此属性设置为 True,则软件包客户端尝试联系用于签名验证的证书中的任何 CRL 分发点,以确定证书自颁发以来是否已被撤销。
+(布尔型)如果此属性设置为 \fBTrue\fR,则软件包客户机将尝试访问用于签名验证的证书中的任何 CRL 分发点,以确定证书自颁发以来是否已被撤销。
 .sp
 缺省值:\fBFalse\fR
 .RE
@@ -1371,7 +2739,7 @@
 .ad
 .sp .6
 .RS 4n
-(布尔型)如果此属性设置为 True,则完成安装或更新操作后,软件包客户端将删除其内容高速缓存中的文件。对于更新操作,仅从源 BE 中删除内容。如果随后目标 BE 中发生了打包操作,并且此选项未发生更改,则软件包客户端将刷新其内容高速缓存。
+(布尔型)如果此属性设置为 \fBTrue\fR,则完成安装或更新操作后,软件包客户机将删除其内容高速缓存中的文件。对于更新操作,仅从源引导环境中删除内容。如果随后目标引导环境中发生了打包操作,并且此选项未发生更改,则软件包客户机将刷新其内容高速缓存。
 .sp
 在磁盘空间有限的系统上,可以使用此属性使内容高速缓存保持为较小的大小。此属性可能会导致花费更长的时间来完成操作。
 .sp
@@ -1386,7 +2754,7 @@
 .ad
 .sp .6
 .RS 4n
-(布尔型)此属性通知客户端使用 mDNS 和 DNS-SD 发现本地链路内容镜像。如果此属性设置为 True,则客户端尝试从其动态发现的镜像中下载软件包内容。要运行一个通过 mDNS 通告其内容的镜像,请参见 \fBpkg.depotd\fR(1M)。
+(布尔型)此属性通知客户端使用 mDNS 和 DNS-SD 发现本地链路内容镜像。如果此属性设置为 \fBTrue\fR,则客户机尝试从其动态发现的镜像中下载软件包内容。要运行一个通过 mDNS 通告其内容的镜像,请参见 \fBpkg.depotd\fR(1M) 手册页。
 .sp
 缺省值:\fBFalse\fR
 .RE
@@ -1399,7 +2767,7 @@
 .ad
 .sp .6
 .RS 4n
-(布尔型)执行网络操作时发送映像的通用唯一标识符 (Universally Unique Identifier, UUID)。尽管用户可以禁用此选项,但是某些网络系统信息库可能会拒绝与不提供 UUID 的客户端通信。
+(布尔型)执行网络操作时发送映像的通用唯一标识符 (Universally Unique Identifier, UUID)。尽管用户可以禁用此选项,但是某些网络系统信息库可能会拒绝与不提供 UUID 的客户机通信。
 .sp
 缺省值:\fBTrue\fR
 .RE
@@ -1412,15 +2780,15 @@
 .ad
 .sp .6
 .RS 4n
-(字符串)确定在映像中安装、更新、修改或验证软件包时,要对清单执行哪些检查。应用于软件包的最终策略取决于映像策略和发布者策略的组合。该策略组合的严格程度至少相当于这两个策略单独执行时较严格的策略。缺省情况下,软件包客户端不检查是否已撤销证书。要启用这些检查(可能需要客户端联系外部 Web 站点),请将 \fBcheck-certificate-revocation\fR 映像属性设置为 \fBtrue\fR。允许使用以下值:
+(字符串)确定在映像中安装、更新、修改或验证软件包时,要对清单执行哪些检查。应用于软件包的最终策略取决于映像策略和发布者策略的组合。该策略组合的严格程度至少相当于这两个策略单独执行时较严格的那一个。缺省情况下,软件包客户机不检查证书是否已撤销。要启用这些检查(可能需要客户机访问外部 Web 站点),请将 \fBcheck-certificate-revocation\fR 映像属性设置为 \fBTrue\fR。允许使用以下值:
 .sp
 .ne 2
 .mk
 .na
 \fB\fBignore\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 忽略所有清单的签名。
 .RE
 
@@ -1430,8 +2798,8 @@
 .na
 \fB\fBverify\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 验证所有具有签名的清单的签名是否有效,但不要求签名所有安装的软件包。这是缺省值。
 .RE
 
@@ -1441,8 +2809,8 @@
 .na
 \fB\fBrequire-signatures\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 要求所有新安装的软件包至少具有一个有效签名。如果安装的软件包不具备有效签名,\fBpkg fix\fR 和 \fBpkg verify\fR 命令也会发出警告。
 .RE
 
@@ -1452,8 +2820,8 @@
 .na
 \fB\fBrequire-names\fR\fR
 .ad
-.RS 22n
-.rt  
+.sp .6
+.RS 4n
 与 \fBrequire-signatures\fR 遵循相同的要求,但还要求 \fBsignature-required-names\fR 属性中列出的字符串显示为用于验证签名信任链的证书的通用名称。
 .RE
 
@@ -1489,13 +2857,13 @@
 .ad
 .sp .6
 .RS 4n
-(布尔型)此属性指示映像是否应使用系统信息库作为映像和发布者配置的源,以及作为与提供的发布者通信的代理。缺省值为 \fBignore\fR。有关系统信息库的信息,请参见 \fBpkg.sysrepo\fR(1M)。
+(布尔型)此属性指示映像是否应使用系统信息库作为映像和发布者配置的源,以及作为与提供的发布者通信的代理。缺省值为 \fBFalse\fR。有关系统信息库的信息,请参见 \fBpkg.sysrepo\fR(1M) 手册页。
 .RE
 
 .SH 发布者属性
 .sp
 .LP
-以下属性是映像的一部分,可使用 \fBset-publisher\fR 子命令的 \fB--set-property\fR 选项进行设置。
+以下属性定义了特定发布者的签名策略。具有相同名称的映像属性定义了该映像的签名策略。要查看特定发布者的这些属性的当前值,请使用 \fBpkg publisher\fR \fIpublisher_name\fR 命令。要修改发布者的这些签名策略属性的值,请使用 \fBpkg set-publisher\fR 命令的 \fB--set-property\fR 和 \fB--unset-property\fR 选项。
 .sp
 .ne 2
 .mk
@@ -1642,21 +3010,105 @@
 .in +2
 .nf
 $ \fBpkg search bge\fR
-INDEX       ACTION VALUE                      PACKAGE
-driver_name driver bge                        pkg:/driver/network/[email protected]
-basename    file   kernel/drv/sparcv9/bge     pkg:/driver/network/[email protected]
-basename    file   kernel/drv/amd64/bge       pkg:/driver/network/[email protected]
-pkg.fmri    set    solaris/driver/network/bge pkg:/driver/network/[email protected]
+INDEX       ACTION VALUE                                 PACKAGE
+driver_name driver bge                                   pkg:/driver/network/ethernet/[email protected]
+basename    file   kernel/drv/sparcv9/bge                pkg:/driver/network/ethernet/[email protected]
+basename    file   kernel/drv/amd64/bge                  pkg:/driver/network/ethernet/[email protected]
+basename    file   platform/sun4v/kernel/drv/sparcv9/bge pkg:/system/kernel/[email protected]
+pkg.fmri    set    solaris/driver/network/bge            pkg:/driver/network/[email protected]
+pkg.fmri    set    solaris/driver/network/ethernet/bge   pkg:/driver/network/ethernet/[email protected]
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+该标记在软件包 \fBdriver/network/bge\fR 中,既用作代表 \fB/kernel/drv/\fI arch\fR/bge\fR 的文件操作的基名,又用作驱动程序名称。
+
+.LP
+\fB示例 8 \fR搜索文件
+.sp
+.LP
+要搜索提供某个文件的软件包,请指定该文件的全路径名,包括开头的斜杠字符。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l /usr/bin/vim\fR
+PATH         PKG.NAME
+usr/bin/vim  editor/vim/vim-core
 .fi
 .in -2
 .sp
 
 .sp
 .LP
-该标记在软件包 \fBdriver/network/bge\fR 中,既用作代表 \fB/kernel/drv/\fI arch\fR/bge\fR 的文件操作的根基名称,又用作驱动程序名称。
+要搜索某个文件和提供该文件的软件包,请指定 \fBfile\fR(对于 \fIaction_name\fR)、\fBpath\fR 或 \fBbasename\fR(对于 \fIindex\fR),以及完整或部分文件名(对于 \fItoken\fR)。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l file:basename:vim\fR
+PATH         PKG.NAME
+usr/bin/vim  editor/vim/vim-core
+.fi
+.in -2
+.sp
 
 .LP
-\fB示例 8 \fR搜索依赖于指定软件包的软件包
+\fB示例 9 \fR搜索文件和目录
+.sp
+.LP
+要搜索文件和目录以及提供它们的软件包,请指定 \fBpath\fR 或 \fBbasename\fR(对于 \fIindex\fR)以及完整或部分文件名(对于 \fItoken\fR)。根据您的 shell,您可能需要对通配符进行转义。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search -o path,pkg.name -l path:*/vim\fR
+PATH           PKG.NAME
+usr/bin/vim    editor/vim/vim-core
+usr/share/vim  editor/vim
+usr/share/vim  editor/vim/vim-core
+$ \fBpkg search -o path,pkg.name -l basename:vim\fR
+PATH           PKG.NAME
+usr/share/vim  editor/vim
+usr/share/vim  editor/vim/vim-core
+usr/bin/vim    editor/vim/vim-core
+.fi
+.in -2
+.sp
+
+.LP
+\fB示例 10 \fR显示哪些软件包提供特定的 SMF 服务
+.sp
+.LP
+要显示哪些软件包提供特定的 SMF 服务,请在结构化搜索中为 \fIindex\fR 指定 \fBorg.opensolaris.smf.fmri\fR 值,并为 \fItoken\fR 指定要查找的服务名称。\fBorg.opensolaris.smf.fmri\fR 值是 \fBset\fR 操作的某个属性的名称。请注意对服务名称中的 : 进行转义。
+
+.sp
+.LP
+例如,要显示哪些 HTTP 服务器可用,请为 \fItoken\fR 指定 \fBsvc:/network/http\fR 值。
+
+.sp
+.in +2
+.nf
+$ \fBpkg search 'org.opensolaris.smf.fmri:svc\e:/network/http*'\fR
+INDEX                    ACTION VALUE                        PACKAGE
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/java-servlet/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http            pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:apache22   pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:lighttpd14 pkg:/web/server/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:privoxy    pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:squid      pkg:/web/proxy/[email protected]
+org.opensolaris.smf.fmri set    svc:/network/http:tomcat6    pkg:/web/java-servlet/[email protected]
+.fi
+.in -2
+.sp
+
+.LP
+\fB示例 11 \fR搜索依赖于指定软件包的软件包
 .sp
 .LP
 搜索依赖于 \fBpackage/pkg\fR 的已安装软件包。
@@ -1664,17 +3116,23 @@
 .sp
 .in +2
 .nf
-$ \fBpkg search -l 'depend::package/pkg'\fR
-INDEX       ACTION VALUE                    PACKAGE
-incorporate depend package/[email protected] pkg:/consolidation/ips/[email protected]
-require     depend package/[email protected] pkg:/system/[email protected]
-require     depend package/[email protected] pkg:/package/pkg/[email protected]
+$ \fBpkg search -l depend::package/pkg\fR
+INDEX       ACTION VALUE                                    PACKAGE
+incorporate depend package/[email protected]      pkg:/consolidation/ips/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/library/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/library/[email protected]
+require     depend package/pkg                             pkg:/system/zones/brand/[email protected]
+require     depend pkg:/package/[email protected] pkg:/install/[email protected]
+require     depend pkg:/package/[email protected] pkg:/system/[email protected]
+require     depend pkg:/package/[email protected] pkg:/package/pkg/[email protected]
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 9 \fR搜索依赖性
+\fB示例 12 \fR搜索依赖性
 .sp
 .LP
 在安装的软件包中搜索所有 \fBincorporate\fR 依赖性。
@@ -1682,17 +3140,17 @@
 .sp
 .in +2
 .nf
-$ \fBpkg search -l 'depend:incorporate:'\fR
-INDEX       ACTION VALUE                           PACKAGE
-incorporate depend pkg:/[email protected],5.11-0.133  pkg:/consolidation/osnet/[email protected]
-incorporate depend pkg:/[email protected],5.11-0.133 pkg:/consolidation/osnet/[email protected]
+$ \fBpkg search -l depend:incorporate:\fR
+INDEX       ACTION VALUE                                PACKAGE
+incorporate depend pkg:/[email protected]  pkg:/consolidation/osnet/[email protected]
+incorporate depend pkg:/[email protected] pkg:/consolidation/osnet/[email protected]
 \&...
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 10 \fR添加发布者
+\fB示例 13 \fR添加发布者
 .sp
 .LP
 添加新的发布者 \fBexample.com\fR,该发布者的系统信息库位于 \fBhttp://www.example.com/repo\fR。
@@ -1706,7 +3164,7 @@
 .sp
 
 .LP
-\fB示例 11 \fR添加具有密钥和证书的发布者
+\fB示例 14 \fR添加具有密钥和证书的发布者
 .sp
 .LP
 添加新的发布者 \fBexample.com\fR,该发布者的安全系统信息库位于 \fBhttps://secure.example.com/repo\fR,其密钥和证书存储在目录 \fB/root/creds\fR 中。
@@ -1722,7 +3180,7 @@
 .sp
 
 .LP
-\fB示例 12 \fR添加并自动配置发布者
+\fB示例 15 \fR添加并自动配置发布者
 .sp
 .LP
 使用自动配置功能添加一个新的发布者,该发布者的系统信息库位于 \fB/export/repo\fR。
@@ -1736,7 +3194,7 @@
 .sp
 
 .LP
-\fB示例 13 \fR添加并手动配置发布者
+\fB示例 16 \fR添加并手动配置发布者
 .sp
 .LP
 使用手动配置功能添加新的发布者 \fBexample.com\fR,该发布者的系统信息库位于 \fB/export/repo/example.com\fR。
@@ -1750,7 +3208,22 @@
 .sp
 
 .LP
-\fB示例 14 \fR验证所有签名的软件包
+\fB示例 17 \fR添加发布者并配置代理
+.sp
+.LP
+添加源为 \fBhttp://server/repo\fR、代理为 \fBhttp://webcache:8080\fR 的新发布者 \fBmypub\fR。
+
+.sp
+.in +2
+.nf
+$ \fBpkg set-publisher -g http://server/repo \e\fR
+\fB--proxy http://webcache:8080 mypub\fR
+.fi
+.in -2
+.sp
+
+.LP
+\fB示例 18 \fR验证所有签名的软件包
 .sp
 .LP
 配置一个映像以验证所有签名的软件包。
@@ -1764,7 +3237,7 @@
 .sp
 
 .LP
-\fB示例 15 \fR要求签名所有软件包
+\fB示例 19 \fR要求签名所有软件包
 .sp
 .LP
 配置一个映像,以要求签名所有软件包,并要求字符串 \fBexample.com\fR 显示为信任链中某一个证书的通用名称。
@@ -1778,7 +3251,7 @@
 .sp
 
 .LP
-\fB示例 16 \fR要求对来自指定发布者的所有软件包进行签名
+\fB示例 20 \fR要求对来自指定发布者的所有软件包进行签名
 .sp
 .LP
 配置一个映像,以便必须对通过发布者 \fBexample.com\fR 安装的所有软件包进行签名。
@@ -1793,7 +3266,7 @@
 .sp
 
 .LP
-\fB示例 17 \fR要求信任链中存在指定的字符串
+\fB示例 21 \fR要求信任链中存在指定的字符串
 .sp
 .LP
 将字符串 \fBfoo\fR 添加到映像的通用名称列表,这些通用名称必须显示在签名的信任链中才能视为有效。
@@ -1807,7 +3280,7 @@
 .sp
 
 .LP
-\fB示例 18 \fR从指定发布者的信任链中删除某个字符串
+\fB示例 22 \fR从指定发布者的信任链中删除某个字符串
 .sp
 .LP
 从通用名称列表中删除字符串 \fBfoo\fR,必须显示这些通用名称才能验证发布者 \fBexample.com\fR 的签名。
@@ -1822,7 +3295,7 @@
 .sp
 
 .LP
-\fB示例 19 \fR添加可信 CA 证书
+\fB示例 23 \fR添加可信 CA 证书
 .sp
 .LP
 添加 \fB/tmp/example_file.pem\fR 中存储的证书,作为发布者 \fBexample.com\fR 的可信 CA 证书。
@@ -1837,7 +3310,7 @@
 .sp
 
 .LP
-\fB示例 20 \fR撤销证书
+\fB示例 24 \fR撤销证书
 .sp
 .LP
 撤销发布者 \fBexample.com\fR 的、包含散列 \fBa12345\fR 的证书,防止该证书验证来自 \fBexample.com\fR 的软件包的任何签名。
@@ -1851,7 +3324,7 @@
 .sp
 
 .LP
-\fB示例 21 \fR忘记针对某个证书执行的操作
+\fB示例 25 \fR忘记针对某个证书执行的操作
 .sp
 .LP
 使 \fBpkg\fR 忘记用户曾经添加或撤销了证书 \fBa12345\fR。
@@ -1865,7 +3338,7 @@
 .sp
 
 .LP
-\fB示例 22 \fR将软件包降级
+\fB示例 26 \fR将软件包降级
 .sp
 .LP
 将安装的软件包 \[email protected]\fR 降级到更低的版本。
@@ -1879,7 +3352,7 @@
 .sp
 
 .LP
-\fB示例 23 \fR切换发生冲突的软件包安装
+\fB示例 27 \fR切换发生冲突的软件包安装
 .sp
 .LP
 当两个软件包发生冲突时,切换所安装的软件包。假定软件包 A 依赖于软件包 B 或软件包 C,而 B 和 C 是互斥的。如果安装了 A 和 B,则使用以下命令即可改为使用 C 而不是 B,且无需卸载 A:
@@ -1893,7 +3366,7 @@
 .sp
 
 .LP
-\fB示例 24 \fR列出软件包归档中的软件包
+\fB示例 28 \fR列出软件包归档中的软件包
 .sp
 .LP
 列出某个软件包归档中所有软件包的所有版本。
@@ -1907,7 +3380,7 @@
 .sp
 
 .LP
-\fB示例 25 \fR列出软件包系统信息库中的软件包
+\fB示例 29 \fR列出软件包系统信息库中的软件包
 .sp
 .LP
 列出某个系统信息库中所有软件包的所有版本。
@@ -1921,7 +3394,7 @@
 .sp
 
 .LP
-\fB示例 26 \fR显示有关软件包归档中某个软件包的信息
+\fB示例 30 \fR显示有关软件包归档中某个软件包的信息
 .sp
 .LP
 显示软件包归档中某个软件包的最新版本的软件包信息。该软件包当前不一定已安装。
@@ -1935,7 +3408,7 @@
 .sp
 
 .LP
-\fB示例 27 \fR显示软件包归档中某个软件包的内容
+\fB示例 31 \fR显示软件包归档中某个软件包的内容
 .sp
 .LP
 显示软件包归档中某个软件包的内容。该软件包当前未安装。
@@ -1949,7 +3422,7 @@
 .sp
 
 .LP
-\fB示例 28 \fR删除发布者的所有源和镜像
+\fB示例 32 \fR删除发布者的所有源和镜像
 .sp
 .LP
 删除某个发布者的所有源和镜像,并添加新的源。
@@ -1983,7 +3456,9 @@
 .ad
 .sp .6
 .RS 4n
-传输操作期间尝试建立连接时等待的秒数(针对每次尝试),达到此秒数后,客户端会异常中止操作。缺省值为 60。
+传输操作期间尝试建立连接时等待的秒数(针对每次尝试),达到此秒数后,客户端会异常中止操作。值 0 表示无限期等待。
+.sp
+缺省值:60
 .RE
 
 .sp
@@ -1994,7 +3469,9 @@
 .ad
 .sp .6
 .RS 4n
-传输操作期间低于 \fBlowspeed\fR 限制(1024 字节/秒)的秒数,达到此秒数后,客户端会异常中止操作。缺省值为 30。
+传输操作期间低于 \fBlowspeed\fR 限制(1024 字节/秒)的秒数,达到此秒数后,客户端会异常中止操作。值 0 表示不中止运行。
+.sp
+缺省值:30
 .RE
 
 .sp
@@ -2005,7 +3482,9 @@
 .ad
 .sp .6
 .RS 4n
-客户端异常中止操作之前发生瞬态传输错误的最大次数。缺省值为 4。
+客户端异常中止操作之前发生瞬态传输错误的最大次数。值 0 表示不中止运行。
+.sp
+缺省值:4
 .RE
 
 .sp
@@ -2016,7 +3495,24 @@
 .ad
 .sp .6
 .RS 4n
-在传输操作期间,异常中止某个连接之前允许的最大 HTTP 或 HTTPS 重定向次数。缺省值为 5。
+在传输操作期间,异常中止某个连接之前允许的最大 HTTP 或 HTTPS 重定向次数。值 0 表示不中止运行。
+.sp
+缺省值:5
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBPKG_CONCURRENCY\fR\fR
+.ad
+.sp .6
+.RS 4n
+要并行更新的子映像数。如果指定了 \fB-C\fR 选项,则会忽略此属性。
+.sp
+在递归检查子映像(通常为区域)时,最多可以并行更新 \fB$PKG_CONCURRENCY\fR 个子映像。如果 \fB$PKG_CONCURRENCY\fR 为 0 或负数,则并行更新所有子映像。
+.sp
+缺省值:1
 .RE
 
 .sp
@@ -2027,7 +3523,9 @@
 .ad
 .sp .6
 .RS 4n
-客户端异常中止操作之前每台主机上的最大传输尝试次数。缺省值为 4。
+客户端异常中止操作之前每台主机上的最大传输尝试次数。值 0 表示不中止运行。
+.sp
+缺省值:4
 .RE
 
 .sp
@@ -2179,8 +3677,8 @@
 .na
 \fB\fB$IMAGE_META/lost+found\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 在软件包操作期间移动的有冲突目录和文件的位置。某个已删除目录的未打包内容的位置。
 .RE
 
@@ -2190,8 +3688,8 @@
 .na
 \fB\fB$IMAGE_META/publisher\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 为每个发布者包含一个目录。每个目录存储特定于发布者的元数据。
 .RE
 
@@ -2201,7 +3699,7 @@
 .SH 属性
 .sp
 .LP
-有关下列属性的描述,请参见 \fBattributes\fR(5):
+有关下列属性的说明,请参见 \fBattributes\fR(5):
 .sp
 
 .sp
--- a/src/man/zh_CN/pkg.5	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkg.5	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkg 5 "2011 年 8 月 30 日" "SunOS 5.11" "标准、环境和宏"
+.\" Copyright (c) 2009, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkg 5 "2012 年 6 月 22 日" "SunOS 5.11" "标准、环境和宏"
 .SH 名称
 pkg \- 映像包管理系统
 .SH 描述
@@ -14,17 +14,17 @@
 .sp
 .in +2
 .nf
-pkg://opensolaris.org/library/[email protected],5.11-0.75:20071001T163427Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z
 .fi
 .in -2
 .sp
 
 .sp
 .LP
-\fBopensolaris.org\fR 是发布者。\fBlibrary/libc\fR 是软件包名称。虽然名称空间是有层次的且可具有任意深度,但不存在强制包含;名称从本质上而言是任意的。发布者信息为可选项,但必须位于 \fBpkg://\fR 之后(如果存在)。包括发布者的 FMRI 通常称为"全限定"FMRI。如果不存在发布者信息,则软件包名称通常应位于 \fBpkg:/\fR 之后。
+\fBsolaris\fR 是发布者。\fBsystem/library/c++-runtime\fR 是软件包名称。虽然名称空间是有层次的且可具有任意深度,但不存在强制包含;名称从本质上而言是任意的。发布者信息为可选项,但必须位于 \fBpkg://\fR 之后(如果存在)。包含发布者的 FMRI 通常称为“全限定”FMRI。如果不存在发布者信息,则软件包名称通常应该位于 \fBpkg:/\fR 之后。
 .sp
 .LP
-如果 FMRI 不包含发布者信息,打包客户端通常允许省略 FMRI 的机制。例如,\fBpkg:/library/libc\fR 可以写为 \fBlibrary/libc\fR。如果省略了机制,客户端也允许省略除软件包名称的最后一个组成部分(用于匹配目的)之外的所有其他内容。例如,\fBlibrary/libc\fR 可写为 \fBlibc\fR,这将与名为 \fBlibc\fR 的软件包或以 \fB/libc\fR 结尾的软件包名称匹配。
+如果 FMRI 不包含发布者信息,打包客户端通常允许省略 FMRI 的机制。例如,\fBpkg:/system/library/c++-runtime\fR 可以写为 \fBsystem/library/c++-runtime\fR。如果省略了机制,客户端也允许省略除软件包名称的最后一个组成部分(用于匹配目的)之外的所有其他内容。例如,\fBsystem/library/c++-runtime\fR 可以写为 \fBlibrary/c++-runtime\fR 或 \fBc++-runtime\fR,这将与名为 \fBc++-runtime\fR 的软件包或以 \fB/c++-runtime\fR 结尾的软件包名称匹配。
 .sp
 .LP
 发布者名称将个人、个人组或组织标识为一个或多个软件包的源。为避免发布者名称冲突并有帮于标识发布者,最佳做法是使用代表发布软件包实体的域名作为发布者名称。
@@ -52,7 +52,7 @@
 .SH 操作
 .sp
 .LP
-操作表示系统上的可安装对象。在软件包的清单中对操作进行了描述。每个操作主要由其名称和一个关键属性组成。这些内容共同引用一个唯一的对象,与该对象一样遵循版本历史记录。操作可以具有其他属性。某些属性由包管理系统直接解释。其他属性可能仅对系统管理员或最终用户有用。
+操作表示系统上的可安装对象。在软件包的清单中对操作进行了描述。每个操作主要由其名称和一个关键属性组成。这些属性共同引用一个唯一的对象,与该对象一样遵循版本历史记录。操作可以具有其他属性。某些属性由包管理系统直接解释。其他属性可能仅对系统管理员或最终用户有用。
 .sp
 .LP
 操作具有一种简单文本表示法:
@@ -65,7 +65,7 @@
 
 .sp
 .LP
-属性名称中不能包含空格、引号或等号 (=)。第一个等号后的所有字符都属于值。值中可以包含所有这些符号,虽然空格必须括在单引号或双引号中。单引号处于括在双引号中的字符串内时不需要进行转义,双引号处于括在单引号中的字符串内时也不需要进行转义。可使用反斜杠 (\\) 字符作为引号的前缀来避免终止带引号的字符串。反斜杠可使用反斜杠进行转义。
+属性名称中不能包含空格、引号或等号 (=)。第一个等号后的所有字符都属于值。值中可以包含所有这些符号,虽然空格必须括在单引号或双引号中。单引号处于括在双引号中的字符串内时不需要进行转义,双引号处于括在单引号中的字符串内时也不需要进行转义。可使用反斜杠 (\e) 字符作为引号的前缀来避免终止带引号的字符串。反斜杠可使用反斜杠进行转义。
 .sp
 .LP
 可以使用多个值对属性进行多次命名。这些值被视为无序列表。
@@ -77,7 +77,7 @@
 下面列出的属性不是全部属性。事实上,任意属性都可附加到操作中,标准属性组易于扩大以合并将来的开发。
 .sp
 .LP
-某些操作属性会导致在打包上下文外部执行其他操作。这些属性记录在下面的"执行器"部分中。
+某些操作属性会导致在打包上下文外部执行其他操作。这些属性记录在下面的“执行器”部分中。
 .SS "文件操作"
 .sp
 .LP
@@ -138,8 +138,8 @@
 .na
 \fB\fBpreserve\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 此属性指定在升级时不应覆盖文件的内容(如果确定自文件安装或上次升级后其内容已发生了更改)。在初始安装时,如果找到现有文件,则挽救该文件(存储在 \fB/var/pkg/lost+found\fR 中)。
 .sp
 如果 \fBpreserve\fR 的值是 \fBrenameold\fR,则使用扩展名 \fB\&.old\fR 重命名现有文件,并将新文件放入相应位置。
@@ -157,8 +157,8 @@
 .na
 \fB\fBoverlay\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 此属性指定操作是允许其他软件包在同一位置提供文件,还是提供用于覆盖其他文件的文件。此功能设计用于不参与任何自组装(例如 \fB/etc/motd\fR)且可安全覆盖的配置文件。
 .sp
 如果未指定 \fBoverlay\fR,多个软件包将无法向同一位置提供文件。
@@ -170,16 +170,16 @@
 
 .sp
 .LP
-也可以"体验"文件,而且文件可根据自身情况具有其他属性。对于 ELF 文件,可识别下列属性:
+也可以“体验”文件,而且文件可根据自身情况具有其他属性。对于 ELF 文件,可识别下列属性:
 .sp
 .ne 2
 .mk
 .na
 \fB\fBelfarch\fR\fR
 .ad
-.RS 17n
-.rt  
-ELF 文件的体系结构。此属性是 \fBuname -p\fR 在构建文件的体系结构上的输出。
+.sp .6
+.RS 4n
+ELF 文件的体系结构。此属性是 \fBuname -p\fR 查询文件所基于的体系结构后的输出。
 .RE
 
 .sp
@@ -188,8 +188,8 @@
 .na
 \fB\fBelfbits\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 此属性为 \fB32\fR 或 \fB64\fR。
 .RE
 
@@ -199,9 +199,9 @@
 .na
 \fB\fBelfhash\fR\fR
 .ad
-.RS 17n
-.rt  
-此属性是文件中"相关"ELF 部分的散列。这些部分已在装入二进制文件时映射到内存中。在确定两个二进制文件的可执行行为是否将不同时,仅需要考虑这些部分。
+.sp .6
+.RS 4n
+此属性是文件中“相关”ELF 部分的散列。这些部分已在装入二进制文件时映射到内存中。在确定两个二进制文件的可执行行为是否将不同时,仅需要考虑这些部分。
 .RE
 
 .sp
@@ -210,8 +210,8 @@
 .na
 \fB\fBoriginal_name\fR\fR
 .ad
-.RS 17n
-.rt  
+.sp .6
+.RS 4n
 此属性用于处理可编辑文件在软件包之间或在位置之间(或在这两者之间)的移动操作。此属性采用的格式为源软件包的名称后跟一个冒号和文件的原始路径。所删除的任何文件将使用其软件包和路径或 \fBoriginal_name\fR 属性的值(如果指定)进行记录。所安装的已设置 \fBoriginal_name\fR 属性的任何可编辑文件将使用具有该名称的文件(如果它在同一打包操作中被删除)。
 .RE
 
@@ -219,11 +219,22 @@
 .ne 2
 .mk
 .na
+\fB\fBrelease-note\fR\fR
+.ad
+.sp .6
+.RS 4n
+该属性用于指明此文件包含发行说明文本。该属性的值为软件包 FMRI。如果 FMRI 指定的软件包名称存在于原始映像中,指定的版本比原始映像中的软件包版本更高,则此文件将成为发行说明的一部分。特殊 FMRI \fBfeature/pkg/self\fR 是指包含软件包。如果 \fBfeature/pkg/self\fR 的版本为 0,则此文件仅在初次安装时是发行说明的一部分。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBrevert-tag\fR\fR
 .ad
-.RS 17n
-.rt  
-此属性用于标记应恢复为一个组的可编辑文件。可以指定多个 revert-tag 值。在使用所指定的任意标记调用 \fBpkg revert\fR 时,文件将恢复为其清单定义的状态。请参见 \fBpkg\fR(1)。
+.sp .6
+.RS 4n
+此属性用于标记应恢复为一个组的可编辑文件。可以指定多个 \fBrevert-tag\fR 值。在使用所指定的任意标记调用 \fBpkg revert\fR 时,文件将恢复为其清单定义的状态。请参见 \fBpkg\fR(1)。
 .RE
 
 .SS "目录操作"
@@ -232,7 +243,7 @@
 \fBdir\fR 操作类似于 \fBfile\fR 操作,因为它表示文件系统对象。但 \fBdir\fR 操作表示目录而不是普通文件。\fBdir\fR 操作具有与 \fBfile\fR 操作相同的四个标准属性,\fBpath\fR 是关键属性。
 .sp
 .LP
-目录是 IPS 中包括的引用。当显式或隐式引用某目录的最新软件包不再引用该目录时,将删除该目录。如果该目录包含未打包的文件系统对象,则将这些项移动到 \fB$IMAGE_META/lost+found\fR 中。有关 \fB$IMAGE_META\fR 的更多信息,请参见"文件"部分。
+目录是 IPS 中包括的引用。当显式或隐式引用某目录的最新软件包不再引用该目录时,将删除该目录。如果该目录包含未打包的文件系统对象,则将这些项移动到 \fB$IMAGE_META/lost+found\fR 中。有关 \fB$IMAGE_META\fR 的更多信息,请参见“文件”部分。
 .sp
 .LP
 要将未打包的内容移动到新的目录中,以下属性可能会有用:
@@ -242,8 +253,8 @@
 .na
 \fB\fBsalvage-from\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 此属性指定所挽救项的目录。具有此属性的目录在创建时可继承所挽救目录的内容(如果存在)。
 .RE
 
@@ -281,7 +292,7 @@
 .ad
 .sp .6
 .RS 4n
-指定由给定中介组(例如 \fBpython\fR)中涉及的所有路径名称共享的中介名称空间中的条目。可基于 \fBmediator-version\fR 和/或 \fBmediator-implementation\fR 执行链接中介。给定路径名称的所有中介链接必须指定同一中介者。但是,并非所有中介者版本和实现都需要在给定路径上提供链接。如果中介不提供链接,则会在选定该中介时删除链接。\fBmediator\fR 与特定版本和/或实现组合起来表示可选择供包管理系统使用的中介。
+指定由给定中介组(例如 \fBpython\fR)中涉及的所有路径名称共享的中介名称空间中的条目。可基于 \fBmediator-version\fR 和/或 \fBmediator-implementation\fR 执行链接中介。给定路径名称的所有中介链接必须指定同一中介。但是,并非所有中介版本和实现都需要在给定路径上提供链接。如果中介不提供链接,则会在选定该中介时删除链接。\fBmediator\fR 与特定版本和/或实现组合起来表示可选择供包管理系统使用的中介。
 .RE
 
 .sp
@@ -303,7 +314,7 @@
 .ad
 .sp .6
 .RS 4n
-指定除 \fBmediator-version\fR 之外还使用中介者实现,或使用中介者实现代替 mediator-version。不认为实现字符串应进行排序,如果系统管理员未显式指定,则由 \fBpkg\fR(5) 任意选择一个字符串。
+指定除 \fBmediator-version\fR 之外还使用中介实现,或使用中介实现代替 mediator-version。不认为实现字符串应进行排序,如果系统管理员未显式指定,则由 \fBpkg\fR(5) 任意选择一个字符串。
 .sp
 该值可以是由字母数字字符和空格组成的任意长度的字符串。如果实现本身可被版本化或已被版本化,则应在字符串的结尾处在 @ 之后指定版本(表示为非负整数的点分序列)。如果存在实现的多个版本,则缺省行为是选择最高版本的实现。
 .sp
@@ -320,7 +331,7 @@
 .RS 4n
 在解决中介链接中的冲突时,\fBpkg\fR(5) 通常会选择 \fBmediator-version\fR 值最大的链接,如果不可能,则会基于 \fBmediator-implementation\fR 进行选择。此属性用于为常规冲突解决方案过程指定覆盖。
 .sp
-如果未指定此属性,则会应用缺省中介者选择逻辑。
+如果未指定此属性,则会应用缺省中介选择逻辑。
 .sp
 如果值为 \fBvendor\fR,则与未指定 \fBmediator-priority\fR 的链接相比,会优先选择该链接。
 .sp
@@ -343,8 +354,8 @@
 .na
 \fB\fBname\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 驱动程序的名称。这通常是(但并不总是)二进制驱动程序文件的文件名。此属性是 \fBdriver\fR 操作的关键属性。
 .RE
 
@@ -354,8 +365,8 @@
 .na
 \fB\fBalias\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性表示驱动程序的别名。给定的驱动程序可以具有多个 \fBalias\fR 属性。无需任何特殊的引号规则。
 .RE
 
@@ -365,8 +376,8 @@
 .na
 \fB\fBclass\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性表示驱动程序类。给定的驱动程序可以具有多个 \fBclass\fR 属性。
 .RE
 
@@ -376,8 +387,8 @@
 .na
 \fB\fBperms\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性表示驱动程序的设备节点的文件系统权限。
 .RE
 
@@ -387,8 +398,8 @@
 .na
 \fB\fBclone_perms\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性表示此驱动程序的克隆驱动程序次要节点的文件系统权限。
 .RE
 
@@ -398,8 +409,8 @@
 .na
 \fB\fBpolicy\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性指定设备的其他安全策略。给定的驱动程序可以具有多个 \fBpolicy\fR 属性,但次要设备规范不可以存在于多个属性中。
 .RE
 
@@ -409,8 +420,8 @@
 .na
 \fB\fBprivs\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 此属性指定驱动程序所用的特权。给定的驱动程序可以具有多个 \fBprivs\fR 属性。
 .RE
 
@@ -420,9 +431,9 @@
 .na
 \fB\fBdevlink\fR\fR
 .ad
-.RS 15n
-.rt  
-此属性指定 \fB/etc/devlink.tab\fR 中的条目。该值是用于进入文件的精确行,带有由 \fB\\t\fR 表示的制表符。有关更多信息,请参见 \fBdevlinks\fR(1M)。给定的驱动程序可以具有多个 \fBdevlink\fR 属性。
+.sp .6
+.RS 4n
+此属性指定 \fB/etc/devlink.tab\fR 中的条目。该值是定义了进入文件的确切行,带有由 \fB\e\et\fR 表示的制表符。有关更多信息,请参见 \fBdevlinks\fR(1M)。给定的驱动程序可以具有多个 \fBdevlink\fR 属性。
 .RE
 
 .SS "依赖操作"
@@ -438,8 +449,8 @@
 .na
 \fB\fBfmri\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 表示依赖软件包的 FMRI。此属性是 \fBdependency\fR 操作的关键属性。\fBfmri\fR 值不得包括发布者。假定软件包名称是完整的。\fBrequire-any\fR 类型的依赖性可具有多个 \fBfmri\fR 属性。\fBfmri\fR 值中的版本是可选项,虽然对于某些类型的依赖性来说,不带版本的 \fBfmri\fR 没有任何意义。
 .RE
 
@@ -449,27 +460,108 @@
 .na
 \fB\fBtype\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 依赖性的类型。
 .sp
-如果值为 \fBrequire\fR,则依赖性是必需的,且必须具有等于或大于 \fBfmri\fR 属性中指定版本的版本。如果未指定版本,则任何版本都满足依赖性。如果不能满足其任一必需依赖性,则无法安装软件包。
+.ne 2
+.mk
+.na
+\fB\fBrequire\fR\fR
+.ad
+.sp .6
+.RS 4n
+该依赖性是必需的,必须具有等于或高于 \fBfmri\fR 属性中所指定版本的版本。如果未指定版本,则任何版本都满足依赖性。如果不能满足其任一必需依赖性,则无法安装软件包。
+.RE
+
 .sp
-如果值为 \fBoptional\fR,则依赖性(如果存在)必须处于指定的版本级别或更高级别。
+.ne 2
+.mk
+.na
+\fB\fBoptional\fR\fR
+.ad
+.sp .6
+.RS 4n
+该依赖性(如果存在)必须处于指定的版本级别或更高级别。
+.RE
+
 .sp
-如果值为 \fBexclude\fR,则当依赖性存在于指定的版本级别或更高级别时,无法安装包含软件包。如果未指定版本,则依赖软件包无法与指定依赖性的软件包同时安装。
+.ne 2
+.mk
+.na
+\fB\fBexclude\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果该依赖性存在于指定的版本级别或更高级别,则无法安装包含软件包。如果未指定版本,则依赖软件包无法与指定依赖性的软件包同时安装。
+.RE
+
 .sp
-如果值为 \fBincorporate\fR,则依赖性是可选的,但依赖软件包的版本会受到约束。请参见下面的"约束和冻结"。
+.ne 2
+.mk
+.na
+\fB\fBincorporate\fR\fR
+.ad
+.sp .6
+.RS 4n
+该依赖性是可选项,但是依赖软件包的版本会受到约束。请参见下文的“约束和冻结”。
+.RE
+
 .sp
-如果值为 \fBrequire-any\fR,则多个 \fBfmri\fR 属性指定的多个依赖软件包中的任一个都可满足依赖性(遵循与 \fBrequire\fR 依赖性类型相同的规则)。
+.ne 2
+.mk
+.na
+\fB\fBrequire-any\fR\fR
+.ad
+.sp .6
+.RS 4n
+多个 \fBfmri\fR 属性指定的多个依赖软件包中的任一个都可满足依赖性(遵循与 \fBrequire\fR 依赖性类型相同的规则)。
+.RE
+
 .sp
-如果值为 \fBconditional\fR,则依赖性仅在系统上存在 \fBpredicate\fR 属性定义的软件包时是必需的。
+.ne 2
+.mk
+.na
+\fB\fBconditional\fR\fR
+.ad
+.sp .6
+.RS 4n
+该依赖性仅在系统上存在 \fBpredicate\fR 属性定义的软件包时才是必需的。
+.RE
+
 .sp
-如果值为 \fBorigin\fR,依赖性(如果存在)必须在要在安装之前修改的映像上具有指定值或更优值。如果 \fBroot-image\fR 属性的值为 \fBtrue\fR,则依赖性必须存在于根目录为 / 的映像上,才能安装此软件包。
+.ne 2
+.mk
+.na
+\fB\fBorigin\fR\fR
+.ad
+.sp .6
+.RS 4n
+该依赖性(如果存在)必须在要在安装之前修改的映像上具有指定值或更优值。如果 \fBroot-image\fR 属性的值为 \fBtrue\fR,则依赖性必须存在于根目录为 / 的映像上,才能安装此软件包。
+.RE
+
 .sp
-如果值为 \fBgroup\fR,则依赖性是必需的,除非软件包出现在映像避免列表上。请注意,过时软件包会无提示地满足组依赖性。请参见 \fBpkg\fR(1) 中的 \fBavoid\fR 子命令。
+.ne 2
+.mk
+.na
+\fB\fBgroup\fR\fR
+.ad
+.sp .6
+.RS 4n
+除非软件包出现在映像避免列表上,否则该依赖性是必需的。请注意,过时软件包会无提示地满足组依赖性。请参见 \fBpkg\fR(1) 中的 \fBavoid\fR 子命令。
+.RE
+
 .sp
-如果值为 \fBparent\fR,则在映像不是子映像时忽略依赖性。如果映像是子映像,则依赖性必须存在于父映像中。符合 \fBparent\fR 依赖性的软件包版本与用于 \fBincorporate\fR 依赖性的软件包版本相同。
+.ne 2
+.mk
+.na
+\fB\fBparent\fR\fR
+.ad
+.sp .6
+.RS 4n
+如果映像不是子映像,会忽略该依赖性。如果映像是子映像,则依赖性必须存在于父映像中。符合 \fBparent\fR 依赖性的软件包版本与用于 \fBincorporate\fR 依赖性的软件包版本相同。
+.RE
+
 .RE
 
 .sp
@@ -478,8 +570,8 @@
 .na
 \fB\fBpredicate\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 表示 \fBconditional\fR 依赖性的谓词的 FMRI。
 .RE
 
@@ -489,8 +581,8 @@
 .na
 \fB\fBroot-image\fR\fR
 .ad
-.RS 14n
-.rt  
+.sp .6
+.RS 4n
 仅对 \fBorigin\fR 依赖性有影响,如上所述。
 .RE
 
@@ -510,8 +602,8 @@
 .na
 \fB\fBlicense\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 此属性是 \fBlicense\fR 操作的关键属性。此属性为许可证提供有意义的描述,以帮助用户在无需阅读许可证文本本身的情况下确定内容。其中一些示例值包括:
 .RS +4
 .TP
@@ -561,7 +653,7 @@
 .el o
 Simplified BSD License
 .RE
-建议尽可能在描述中包括许可证的版本,如上所示。\fBlicense\fR 值在软件包内必须唯一。
+\fBlicense\fR 值在软件包内必须唯一。建议在说明中包括许可证的版本,如上面的几个示例所示。如果软件包有对应多种不同许可证的代码,请使用多个 \fBlicense\fR 操作。许可证属性值的长度不得超过 64 个字符。
 .RE
 
 .sp
@@ -570,8 +662,8 @@
 .na
 \fB\fBmust-accept\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBtrue\fR,则用户必须先接受此许可证,才能安装或更新相关软件包。省略此属性等效于 \fBfalse\fR。接受的方法(例如,交互式或基于配置)由客户端决定。
 .RE
 
@@ -581,8 +673,8 @@
 .na
 \fB\fBmust-display\fR\fR
 .ad
-.RS 16n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBtrue\fR,则在执行打包操作期间客户端必须显示操作的有效负荷。省略此值等效于 \fBfalse\fR。此属性不应用于版权声明,仅用于实际许可证或执行操作期间必须显示的其他材料。显示的方法由客户端决定。
 .RE
 
@@ -599,8 +691,8 @@
 .na
 \fB\fBcategory\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBCATEGORY\fR 参数的值。缺省值为 \fBsystem\fR。
 .RE
 
@@ -610,8 +702,8 @@
 .na
 \fB\fBdesc\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBDESC\fR 参数的值。
 .RE
 
@@ -621,8 +713,8 @@
 .na
 \fB\fBhotline\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBHOTLINE\fR 参数的值。
 .RE
 
@@ -632,8 +724,8 @@
 .na
 \fB\fBname\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBNAME\fR 参数的值。缺省值为 \fBnone provided\fR。
 .RE
 
@@ -643,8 +735,8 @@
 .na
 \fB\fBpkg\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 要安装的软件包的缩写。缺省值为软件包的 FMRI 中的名称。此属性是 \fBlegacy\fR 操作的关键属性。
 .RE
 
@@ -654,8 +746,8 @@
 .na
 \fB\fBvendor\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 \fBVENDOR\fR 参数的值。
 .RE
 
@@ -665,8 +757,8 @@
 .na
 \fB\fBversion\fR\fR
 .ad
-.RS 12n
-.rt  
+.sp .6
+.RS 4n
 VERSION 参数的值。缺省值为软件包的 FMRI 中的版本。
 .RE
 
@@ -706,10 +798,21 @@
 .ne 2
 .mk
 .na
+\fB\fBpkg.fmri\fR\fR
+.ad
+.sp .6
+.RS 4n
+请参见“描述”部分中的“软件包 FMRI 和版本”。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fBinfo.classification\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 一个 \fBpkg\fR(5) 客户端可以使用一个或多个标记对软件包进行分类。该值应具有一个机制(例如 "org.opensolaris.category.2008" 或 "org.acm.class.1998")和实际分类(例如 "Applications/Games"),由冒号 (:) 分隔。
 .RE
 
@@ -719,8 +822,8 @@
 .na
 \fB\fBpkg.description\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 软件包的内容和功能的详细描述,长度通常约为一个段落。
 .RE
 
@@ -730,8 +833,8 @@
 .na
 \fB\fBpkg.obsolete\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBtrue\fR,则将软件包标记为过时。过时的软件包除了设置操作外不能具有任何其他操作,且不得标记为已重命名。
 .RE
 
@@ -741,8 +844,8 @@
 .na
 \fB\fBpkg.renamed\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBtrue\fR,则软件包已被重命名。软件包中还必须存在一个或多个 \fBdepend\fR 操作,且指向此软件包已重命名到的软件包版本。软件包不能同时标记为已重命名和过时,但在其他情况下可以具有任意多个设置操作。
 .RE
 
@@ -752,8 +855,8 @@
 .na
 \fB\fBpkg.summary\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 软件包的一行简短描述。
 .RE
 
@@ -767,8 +870,8 @@
 .na
 \fB\fBgroupname\fR\fR
 .ad
-.RS 13n
-.rt  
+.sp .6
+.RS 4n
 组名的值。
 .RE
 
@@ -778,8 +881,8 @@
 .na
 \fB\fBgid\fR\fR
 .ad
-.RS 13n
-.rt  
+.sp .6
+.RS 4n
 组的唯一数字 ID。缺省值为 100 之下的第一个自由组。
 .RE
 
@@ -796,8 +899,8 @@
 .na
 \fB\fBusername\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的唯一名称
 .RE
 
@@ -807,8 +910,8 @@
 .na
 \fB\fBpassword\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的加密口令。缺省值为 \fB*LK*\fR。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -818,8 +921,8 @@
 .na
 \fB\fBuid\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的唯一 UID。缺省值为 100 之下的第一个自由值。
 .RE
 
@@ -829,8 +932,8 @@
 .na
 \fB\fBgroup\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的主组名称。必须可在 \fB/etc/group\fR 中找到。
 .RE
 
@@ -840,8 +943,8 @@
 .na
 \fB\fBgcos-field\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 \fB/etc/passwd\fR 中 \fBgcos\fR 字段的值。缺省值为 \fBusername\fR。
 .RE
 
@@ -851,8 +954,8 @@
 .na
 \fB\fBhome-dir\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的起始目录。缺省值为 /。
 .RE
 
@@ -862,8 +965,8 @@
 .na
 \fB\fBlogin-shell\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户的缺省 shell。缺省值为空。
 .RE
 
@@ -873,8 +976,8 @@
 .na
 \fB\fBgroup-list\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户所属的辅助组。请参见 \fBgroup\fR(4)。
 .RE
 
@@ -884,8 +987,8 @@
 .na
 \fB\fBftpuser\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 可设置为 \fBtrue\fR 或 \fBfalse\fR。缺省值 \fBtrue\fR 指示允许用户通过 FTP 登录。请参见 \fBftpusers\fR(4)。
 .RE
 
@@ -895,8 +998,8 @@
 .na
 \fB\fBlastchg\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 1970 年 1 月 1 日至上次修改口令的日期之间的天数。缺省值为空。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -906,8 +1009,8 @@
 .na
 \fB\fBmin\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 所需的相邻两次更改口令之间的最小天数。必须将此字段设置为 0 或更大值才能启用口令有效期。缺省值为空。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -917,8 +1020,8 @@
 .na
 \fB\fBmax\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 口令的最大有效天数。缺省值为空。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -928,8 +1031,8 @@
 .na
 \fB\fBwarn\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 用户在口令到期之前多少天收到警告。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -939,8 +1042,8 @@
 .na
 \fB\fBinactive\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 允许该用户不活动的天数。按每台计算机对此进行计数。可从计算机的 \fBlastlog\fR 文件获取有关上次登录的信息。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -950,8 +1053,8 @@
 .na
 \fB\fBexpire\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 表示为自 UNIX 纪元(1970 年 1 月 1 日)后的天数的绝对日期。达到此数字时,将无法再进行登录。例如,到期值为 13514 指定登录将在 2007 年 1 月 1 日失效。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -961,8 +1064,8 @@
 .na
 \fB\fBflag\fR\fR
 .ad
-.RS 15n
-.rt  
+.sp .6
+.RS 4n
 设置为空。请参见 \fBshadow\fR(4)。
 .RE
 
@@ -984,7 +1087,7 @@
 .ad
 .sp .6
 .RS 4n
-可设置为 \fBtrue\fR 或 \fBfalse\fR。如果在软件包安装期间安装或更新某个操作(此执行器设置为 \fBtrue\fR),则可以将打包事务通告为需要重新引导。某些客户端实现可能会执行附加步骤,例如,在映像是实时系统映像的情况下,使用该映像的克隆执行整个软件包操作。
+可设置为 \fBtrue\fR 或 \fBfalse\fR。此执行器声明:如果软件包系统在实时映像上操作,则必须在新引导环境中更新或删除标记的操作。\fBbe-policy\fR 映像属性控制新引导环境的创建。有关 \fBbe-policy\fR 属性的更多信息,请参见 \fBpkg\fR(1) 手册页的“映像属性”部分。
 .RE
 
 .sp
@@ -995,30 +1098,48 @@
 .ad
 .sp .6
 .RS 4n
-其中每个执行器在软件包安装或删除过程中均使用服务实例的 FMRI 值进行操作。根据 \fBsvcadm\fR(1M) 的 \fBdisable\fR 子命令,\fBdisable_fmri\fR 会导致给定的 FMRI 在删除操作之前被禁用。根据 \fBsvcadm\fR(1M) 的各个子命令,\fBrefresh_fmri\fR 和 \fBrestart_fmri\fR 会导致给定的 FMRI 在安装或更新操作后被刷新或重新启动。最后,\fBsuspend_fmri\fR 会导致给定的 FMRI 在安装操作阶段之前被临时禁用,并在该阶段完成后被重新启用。
+其中每个执行器在软件包安装或删除过程中均使用服务实例的 FMRI 值进行操作。根据 \fBsvcadm\fR(1M) 的 \fBdisable\fR 子命令,\fBdisable_fmri\fR 会导致给定的 FMRI 在删除操作之前被禁用。根据 \fBsvcadm\fR(1M) 的各个子命令,\fBrefresh_fmri\fR 和 \fBrestart_fmri\fR 会导致给定的 FMRI 在安装、更新或删除操作后被刷新或重新启动。最后,\fBsuspend_fmri\fR 会导致给定的 FMRI 在安装操作阶段之前被临时禁用,并在该阶段完成后被重新启用。
 .sp
 该值可以包含与多个服务实例匹配的模式。但是,它必须使用 \fBsvcs\fR(1) 所接受的 glob 显式执行此操作,而不是通过不指示任何实例来隐式执行此操作。
 .RE
 
+.SH 中介
+.sp
+.LP
+中介是代表一组相关符号链接或硬链接的名称。如果两个或更多个链接操作拥有相同的路径和中介名称,则用户或软件包系统会根据版本、实现或优先级选择链接目标。有关中介属性的信息,请参见“链接操作”。
+.sp
+.LP
+以下示例显示名为 \fBjava\fR 的中介的两个不同实例(其中,链接选择的区别为版本)。这两个 \fBlink\fR 操作会显示在两个不同软件包中。
+.sp
+.in +2
+.nf
+link mediator=java mediator-version=1.6 path=usr/java target=jdk/jdk1.6.0_31
+link mediator=java mediator-version=1.7 path=usr/java target=jdk/jdk1.7.0_02
+.fi
+.in -2
+
+.sp
+.LP
+有关如何为此链接路径选择所需版本的信息,请参见 \fBpkg\fR(1) 手册页中的 \fBset-mediator\fR 子命令。要选择版本,必须安装两个软件包。
 .SH 约束和冻结
 .sp
 .LP
 在将软件包转换为新版本、添加到系统中或从系统中删除时,所选的版本或是否允许删除由对软件包施加的各种约束确定。这些约束可由其他软件包以依赖性的形式进行定义,或者由管理员以冻结的形式进行定义。
 .sp
 .LP
-最常见的约束形式由 \fBrequire\fR 依赖性提供,如上面的"依赖操作"中所述。此类约束可防止软件包被降级或删除。
+最常见的约束形式由 \fBrequire\fR 依赖性提供,如上面的“依赖操作”中所述。此类约束可防止软件包被降级或删除。
 .sp
 .LP
-操作系统的大多数部分由名为 \fBincorporation\fR 的软件包进行封装。这些软件包主要提供由 \fBincorporate\fR 依赖性表示的约束。
+操作系统的大多数部分由名为 \fB incorporation\fR 的软件包进行封装。这些软件包主要提供由 \fBincorporate\fR 依赖性表示的约束。
 .sp
 .LP
-如上所述,合并的软件包不需要存在于系统上,但如果存在,它将同时指定一个非独占最低版本和一个独占最高版本。例如,如果依赖 FMRI 具有版本 1.4.3,则低于 1.4.3 的版本都不能满足依赖性,且任何高于或等于 1.4.4 的版本也都不能满足依赖性。但是,允许使用仅扩展点分序列的版本(例如 1.4.3.7)。
+如上所述,合并的软件包不需要存在于系统上,但如果存在,它将同时指定一个非独占最低版本和一个独占最高版本。例如,如果依赖性的 FMRI 具有版本 1.4.3,则低于 1.4.3 的版本不能满足依赖性,且任何高于或等于 1.4.4 的版本也不能满足依赖性。但是,可以允许仅仅扩展了点分序列的版本,如 1.4.3.7。
 .sp
 .LP
 Incorporation 用于强制系统的各部分进行同步升级。对于某些组件(例如 C 库和内核),这是一项基本要求。对于其他组件(例如,不具有任何其他依赖性的简单用户级组件),同步升级仅仅用来提供一组经过测试的已知软件包版本,这些软件包版本可由 incorporation 的特定版本进行引用。
 .sp
 .LP
-因为 incorporation 只是一个软件包,所以可将其删除,它提供的所有约束也将随之解除。但是,Oracle Solaris 提供的许多 incorporation 是合并软件包所必需的,因为解除其约束可能会不安全。
+因为 incorporation 只是一个软件包,所以可将其删除,它提供的所有约束也将随之解除。但是,Oracle Solaris 提供的许多 incorporation 是其合并的软件包所必需的,因为解除其约束可能会不安全。
 .sp
 .LP
 尝试将软件包升级到已安装的 incorporation 所不允许的版本,将不会尝试查找更高的 incorporation 版本来满足该请求,反而会失败。如果必须移动约束本身,而又无法删除指定它的 incorporation,则必须将 incorporation 升级到指定所需约束版本的版本。升级 incorporation 会导致不能满足新版本提供的约束的所有合并软件包也进行升级。
@@ -1038,40 +1159,130 @@
 .sp
 .LP
 \fBmirror\fR 是仅包含软件包内容(文件)的软件包系统信息库。如果在一个映像中为给定发布者配置了一个或多个镜像,则客户端 API 会优先使用镜像进行软件包内容检索并尝试选择从其检索软件包内容的最佳镜像。如果镜像不可访问、不具有所需内容或者运行缓慢,客户端 API 将从任何已配置的源系统信息库检索内容。镜像设计用于通过 \fBpkg.depotd\fR(1M) 的动态镜像功能在一组可信客户端之间共享内容。镜像还设计用于验证对软件包元数据的访问,但发行软件包内容不需要进行验证。例如,客户端可能配置有需要具有 SSL 密钥和证书对才能访问的 \fBhttps\fR 源,以及提供软件包内容的 \fBhttp\fR 镜像。这样,只有经过授权的客户端才可以安装或更新软件包,同时避免了验证软件包内容检索的开销。通过删除系统信息库中除名为 \fBfile\fR 的子目录及其父目录之外的所有子目录可创建镜像。通过使用 \fBpkg.depotd\fR(1M) 的镜像模式还可将源系统信息库置备为镜像。
-.SH 属性
+.SH 全局和非全局区域更新
+.sp
+.LP
+\fBpkg\fR 系统会强制使非全局区域与全局区域保持同步。这表示某些软件包在全局区域和所有非全局区域中必须处于同一版本,以确保运行相同的内核。为此,\fBpkg\fR 会使用 \fBparent\fR 依赖性对非全局区域施加某些约束。有关 \fBparent\fR 依赖性的更多信息,请参见“依赖操作”。
+.sp
+.LP
+由于全局区域对非全局区域施加的限制,非全局区域必须可以访问全局区域的软件包且必须具有相似的发布者配置。使用\fB系统信息库\fR可实现上述两个目标(请参见 \fBpkg.sysrepo\fR(1M) 手册页)。系统信息库可提供全局区域中配置的发布者的访问权,以及有关如何配置这些发布者的信息。要阻止非全局区域在安装或更新期间选择不同软件包,在发布者搜索顺序中系统发布者的排列顺序需要高于非全局区域中配置的发布者的顺序。有关发布者搜索顺序的信息,请参见 \fBpkg\fR(1) 手册页中的 \fBpkg set-publisher\fR 命令。
+.sp
+.LP
+要更新系统上的所有非全局区域,请使用不带全局区域中参数的 \fBpkg update\fR 命令。此命令会在全局区域上执行并以递归方式在每个非全局区域上执行。将对非全局区域仅进行最少的必要更改,以使其与全局区域中所进行的更改同步。例如,假设全局区域和非全局区域中都安装了版本 1 的软件包 \fBfoo\fR,并假设系统信息库中存在版本 2。如果 \fBfoo\fR 具有父项依赖性,则 \fBpkg update foo\fR 会在全局区域和非全局区域中将 \fBfoo\fR 更新至版本 2,这是因为 \fBparent\fR 依赖性会强制使软件包保持同步。如果 \fBfoo\fR 不具有父项依赖性,则 \fBfoo\fR 在全局区域中会更新至版本 2,但在非全局区域中仍为版本 1。
+.SH 侧面和变量
+.sp
+.LP
+软件可以具有可选组件和互斥组件。可选组件的示例包括语言环境和文档。互斥组件的示例包括 SPARC 或 x86 和调试或非调试二进制文件。
+.sp
+.LP
+在 IPS 中,可选组件称为\fB侧面\fR,互斥组件称为\fB变量\fR。侧面和变量指定为软件包操作中的标记。每个侧面和变量标记都有一个名称和值。单个操作可以具有多个侧面和变量标记。具有多个侧面和变量标记的组件有多种,例如供开发者使用的特定于体系结构的头文件,或仅用于 SPARC 全局区域的组件。
+.sp
+.LP
+以下是变量标记的一个示例 \fBvariant.arch=sparc\fR。以下是侧面标记的一个示例 \fBvariant.arch=sparc\fR。引用侧面和变量时,通常不带前导字符串 \fBfacet.\fR 和 \fBvariant.\fR。
+.sp
+.LP
+侧面和变量是映像的特殊属性,无法在单个软件包上设置。要查看映像上设置的侧面和变量的当前值,请按 \fBpkg\fR(1) 手册页中所示,使用 \fBpkg facet\fR 和 \fBpkg variant\fR 命令。要修改映像上设置的侧面和变量的值,请使用 \fBpkg change-facet\fR 和 \fBpkg change-variant\fR 命令。
+.sp
+.LP
+侧面为布尔型:只能设置为 \fBtrue\fR(启用)或 \fBfalse\fR(禁用)。缺省情况下,映像中的所有侧面都被视为 \fBtrue\fR。某一操作的侧面标记只能具有 \fBtrue\fR 值;其他值代表的行为不确定。映像上设置的侧面可以为完整侧面(如 \fBdoc.man\fR)或模式(如 \fBlocale.*\fR)。要禁用侧面名称空间的一部分,仅启用其中的几个侧面时,此方式很有用。例如,您可以禁用所有语言环境,然后仅启用一个或两个特定语言环境,如以下示例所示:
+.sp
+.in +2
+.nf
+# \fBpkg change-facet locale.*=false\fR
+[output about packages being updated]
+# \fBpkg change-facet locale.en_US=true\fR
+[output about packages being updated]
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+大多数变量可以具有任意数量的值。例如,\fBarch\fR 变量可以设置为 \fBi386\fR、\fBsparc\fR、\fBppc\fR、\fBarm\fR 或分发支持的任何体系结构。(Oracle Solaris 中仅使用 \fBi386\fR 和 \fBsparc\fR。)但 \fBdebug\fR 变量例外。\fBdebug\fR 变量只能设置为 \fBtrue\fR 或 \fBfalse\fR;其他值的行为不确定。如果文件操作同时具有非调试和调试版本,则必须针对这两个版本明确设置适用的 \fBdebug\fR 变量,如以下示例所示:
+.sp
+.in +2
+.nf
+file group=sys mode=0644 overlay=allow owner=root \e
+  path=etc/motd pkg.csize=115 pkg.size=103 preserve=true \e
+  variant.debug.osnet=true
+
+file group=sys mode=0644 overlay=allow owner=root \e
+  path=etc/motd pkg.csize=68 pkg.size=48 preserve=true \e
+  variant.debug.osnet=false 
+.fi
+.in -2
+
+.sp
+.LP
+要安装使用变量的软件包,必须在映像上设置变量值。\fBarch\fR 和 \fBzone\fR 变量由创建映像和安装其初始内容的程序设置。缺省情况下,\fBdebug.*\fR 变量在映像中设置为 \fBfalse\fR。
 .sp
 .LP
-映像可具有一个或多个与其关联的属性。这些属性可用来存储有关映像的用途、内容和行为的信息。有关完整列表,请参见 \fBpkg\fR(1)。
+映像中设置的侧面和变量会影响是否安装特定操作。
+.RS +4
+.TP
+.ie t \(bu
+.el o
+始终会安装不带侧面或变量标记的操作。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+仅当与侧面标记匹配的所有侧面或侧面模式在映像中都设置为 \fBfalse\fR 时,才不会安装带这些标记的操作。只要有任何侧面设置为 \fBtrue\fR 或未明确设置(\fBtrue\fR 为缺省值),就会安装该操作。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+仅当所有变量标记的值与映像中设置的值相同时,才会安装带这些变量标记的操作。
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+如果侧面和变量都允许安装操作,则会安装带有这两种标记的操作。
+.RE
+.sp
+.LP
+您可以创建自己的侧面和变量标记。以下是 Oracle Solaris 中的常用标记。
+.sp
+
+.sp
+.TS
+tab();
+cw(2.75i) cw(2.75i) 
+lw(2.75i) lw(2.75i) 
+.
+变量名可能值
+_
+\fBvariant.arch\fR\fBsparc\fR, \fBi386\fR
+\fBvariant.opensolaris.zone\fR\fBglobal\fR, \fBnonglobal\fR
+\fBvariant.debug.*\fR\fBtrue\fR、\fBfalse\fR
+.TE
+
+.sp
+.LP
+以下列表描述了 Oracle Solaris 中使用的一小部分侧面标记:
+.sp
+.in +2
+.nf
+facet.devel             facet.doc
+facet.doc.html          facet.doc.info
+facet.doc.man           facet.doc.pdf
+facet.locale.de         facet.locale.en_GB
+facet.locale.en_US      facet.locale.fr
+facet.locale.ja_JP      facet.locale.zh_CN
+.fi
+.in -2
+
 .SH 映像策略
 .sp
 .LP
-策略由带有布尔值的映像属性所定义。支持的策略包括:
-.sp
-.ne 2
-.mk
-.na
-\fB\fBflush-content-cache-on-success\fR\fR
-.ad
-.sp .6
-.RS 4n
-如果为 true,则在成功安装软件包之后删除已下载文件的高速缓存。缺省值:\fBTrue\fR。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fBsend-uuid\fR\fR
-.ad
-.sp .6
-.RS 4n
-如果为 true,则对所有请求发送向发布者标识映像的唯一标识符 (UUID)。缺省值:\fBTrue\fR。
-.RE
-
+映像策略由具有布尔值的映像属性所定义。有关 \fBflush-content-cache-on-success\fR 和 \fBsend-uuid\fR 属性的说明以及如何查看和修改其值的信息,请参见 \fBpkg\fR(1) 手册页中的“映像属性”。
 .SH 文件
 .sp
 .LP
-因为在较大的文件系统内可以任意找到 \fBpkg\fR(5) 映像,所以标记 \fB$IMAGE_ROOT\fR 可用于区分相对路径。对于典型的系统安装,\fB$IMAGE_ROOT\fR 等效于 /。
+因为 \fBpkg\fR(5) 映像可位于任意一个较大的文件系统内,需要使用标记 \fB$IMAGE_ROOT\fR 来区分相对路径。对于典型的系统安装,\fB$IMAGE_ROOT\fR 等效于 /。
 .sp
 .ne 2
 .mk
@@ -1096,15 +1307,15 @@
 
 .sp
 .LP
-在特定映像的元数据中,某些文件和目录可能包含修复和恢复期间有用的信息。标记 \fB$IMAGE_META\fR 用于引用元数据所在的顶层目录。\fB$IMAGE_META\fR 通常是上述两个路径之一。
+在特定映像的元数据中,某些文件和目录可能包含修复和恢复期间有用的信息。标记 \fB$IMAGE_META \fR 用于指示包含元数据的顶层目录。\fB $IMAGE_META\fR 通常是以上给出的两个路径之一。
 .sp
 .ne 2
 .mk
 .na
 \fB\fB$IMAGE_META/lost+found\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 在软件包操作期间移动的有冲突目录和文件的位置。
 .RE
 
@@ -1114,18 +1325,18 @@
 .na
 \fB\fB$IMAGE_META/publisher\fR\fR
 .ad
-.RS 26n
-.rt  
+.sp .6
+.RS 4n
 为每个发布者包含一个目录。每个目录存储特定于发布者的元数据。
 .RE
 
 .sp
 .LP
-\fB$IMAGE_META\fR 目录分层结构中的其他路径是"专用的",可能会进行更改。
+\fB$IMAGE_META\fR 目录分层结构中的其他路径是专用的,但可以进行更改。
 .SH 属性
 .sp
 .LP
-有关下列属性的描述,请参见 \fBattributes\fR(5):
+有关下列属性的说明,请参见 \fBattributes\fR(5):
 .sp
 
 .sp
@@ -1144,7 +1355,16 @@
 .SH 另请参见
 .sp
 .LP
-\fBpkg\fR(1)、\fBpkgsend\fR(1)、\fBpkg.depotd\fR(1M)、\fBsvcadm\fR(1M)、\fBpkginfo\fR(4)
+\fBpkg \fR(1)、\fBpkg\fR(1)、\fBpkg\fR(1M)、\fBpkg\fR(1M)、\fBsvcs\fR(1)、\fBsvcadm\fR(1M)
+.sp
+.LP
+《\fI《添加和更新 Oracle Solaris 11.1 软件包》\fR》
+.sp
+.LP
+《\fI《复制和创建 Oracle Solaris 11.1 软件包系统信息库》\fR》
+.sp
+.LP
+《\fI《Packaging and Delivering Software With the Oracle Solaris 11 Image Packaging System》\fR》
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/zh_CN/pkgdepend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgdepend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgdepend 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkgdepend 1 "2012 年 6 月 22 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgdepend \- 映像包管理系统依赖项分析器
 .SH 用法概要
@@ -12,19 +12,19 @@
 .LP
 .nf
 /usr/bin/pkgdepend generate [-IMm] -d \fIdir\fR [-d \fIdir\fR]
-    [-D \fIname\fR=\fIvalue\fR] [-k \fIpath\fR] \fImanifest_path\fR
+    [-D \fIname\fR=\fIvalue\fR] [-k \fIpath\fR] \fImanifest_file\fR
 .fi
 
 .LP
 .nf
 /usr/bin/pkgdepend resolve [-moSv] [-d \fIoutput_dir\fR]
-    [-s \fIsuffix\fR] \fImanifest_path\fR ...
+    [-s \fIsuffix\fR] \fImanifest_file\fR ...
 .fi
 
 .SH 描述
 .sp
 .LP
-\fBpkgdepend\fR 用于生成并解析软件包的依赖项。软件包可能依赖于其他软件包中的文件。\fBpkgdepend\fR 通常用于两种传递:文件依赖项生成和文件到软件包的解析。
+\fBpkgdepend\fR 命令生成并解析软件包的依赖项。某个软件包可能会依赖于其他软件包中的文件。\fBpkgdepend\fR 命令通常使用两次:一次用于文件依赖项生成和一次用于文件到软件包的解析。
 .sp
 .LP
 \fBgenerate\fR 子命令将检查软件包的内容,并确定该软件包所需的外部文件。
@@ -42,7 +42,7 @@
 .ad
 .RS 13n
 .rt  
-分析提供的文件中的 ELF 头以获取依赖项信息,\fB-k\fR 和 \fB-D\fR 选项可用于修改获取的信息。有关 ELF 依赖项的更多详细信息,请参见 \fBldd\fR(1) 和\fI《Linker and Libraries Guide》\fR。
+分析提供的文件中的 ELF 头以获取依赖项信息,\fB-k\fR 和 \fB-D\fR 选项可用于修改获取的信息。有关 ELF 依赖项的更多详细信息,请参见 \fBldd\fR 和\fI《Linker and Libraries Guide》\fR。
 .RE
 
 .sp
@@ -97,22 +97,30 @@
 .ne 2
 .mk
 .na
-\fB\fB-R\fR \fIdir\fR\fR
+\fB\fB-?\fR\fR
 .ad
-.RS 17n
-.rt  
-对根目录为 \fIdir\fR 的映像进行操作。如果未根据环境指定或确定目录,则缺省值为 /。有关更多信息,请参见"环境变量"部分。
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--help\fR 或 \fB-?\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
 .ad
-.RS 17n
-.rt  
-显示用法消息。
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
+对根目录为 \fIdir\fR 的映像进行操作。如果未根据环境指定或确定目录,则缺省值为 /。有关更多信息,请参见“环境变量”部分。
 .RE
 
 .SH 子命令
@@ -123,33 +131,84 @@
 .ne 2
 .mk
 .na
-\fB\fBgenerate [\fB-IMm\fR] \fB-d\fR \fI dir\fR [\fB-d\fR \fIdir\fR] [\fB-D\fR \fI name\fR=\fIvalue\fR] [\fB-k\fR \fI path\fR] \fImanifest_path\fR\fR\fR
+\fB\fBpkgdepend generate\fR [\fB-IMm\fR] \fB- d\fR \fIdir\fR [\fB-d\fR \fIdir\fR] [\fB-D\fR \fIname\fR=\fIvalue\fR] [\fB-k\fR \fIpath\fR] \fImanifest_file\fR\fR
+.ad
+.sp .6
+.RS 4n
+生成由 \fImanifest_file\fR 指定的清单文件的依赖项。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-I\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示 \fImanifest_file\fR 中满足条件的依赖项。请勿使用带 \fB-I\fR 选项的 \fBpkgdepend resolve\fR 命令产生的结果。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-M\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示无法分析的文件类型的列表。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
 .ad
 .sp .6
 .RS 4n
-生成由 \fImanifest_path\fR 指定的清单文件的依赖项。
-.sp
-与 \fB-I\fR 一起使用时,将显示在给定清单中满足条件的依赖项。
+重复显示原始清单,并在其后添加发现的任何依赖项。
+.RE
+
 .sp
-与 \fB-M\fR 一起使用时,将显示无法分析的文件类型的列表。
-.sp
-与 \fB-m\fR 一起使用时,将重复原始清单,并在其后添加任何发现的依赖项。
+.ne 2
+.mk
+.na
+\fB\fB-d\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
+将 \fIdir\fR 添加到搜索清单文件的目录列表。
+.RE
+
 .sp
-与 \fB-d\fR 一起使用时,将 \fIdir\fR 添加到目录列表以搜索清单的文件。
-.sp
-对于每个 \fB-D\fR,将添加 \fIvalue\fR,作为在 ELF 文件依赖项的运行路径中扩展标记 \fIname\fR 的一种方法。
+.ne 2
+.mk
+.na
+\fB\fB-D\fR \fIname\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+添加 \fIvalue\fR,将其作为在 ELF 文件依赖项的运行路径中扩展标记 \fIname\fR 的一种方法。
+.RE
+
 .sp
-对于每个 \fB-k\fR,将 \fIpath\fR 添加到运行路径的列表,以搜索内核模块。使用 \fB-k\fR 参数会删除缺省路径 \fB/kernel\fR 和 \fB/usr/kernel\fR。
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIpath\fR\fR
+.ad
+.sp .6
+.RS 4n
+将 \fIpath\fR 添加到搜索内核模块的运行路径列表。使用 \fB-k\fR 选项会删除缺省路径 \fB/kernel\fR 和 \fB/usr/kernel\fR。
 .sp
-运行路径(例如 \fB-k\fR 选项指定的那些运行路径)也可以通过使用操作或清单属性 \fBpkg.depend.runpath\fR 来按操作或清单指定。\fBpkg.depend.runpath \fR 属性的值是要使用的路径的冒号分隔字符串。
-.sp
-使用的 \fB-k\fR 将被清单或操作中设置的任何 \fBpkg.depend.runpath \fR 属性覆盖。
+运行路径(例如 \fB-k\fR 选项指定的那些运行路径)也可以通过使用操作或清单属性 \fBpkg.depend.runpath\fR 来按操作或清单指定。\fBpkg.depend.runpath \fR 属性的值是要使用的路径的冒号分隔字符串。在清单或操作中设置任何 \fBpkg.depend.runpath\fR 属性时均会覆盖使用 \fB-k\fR 选项指定的路径。
 .sp
 特殊标记 \fB$PKGDEPEND_RUNPATH\fR 可用作 \fBpkg.depend.runpath\fR 属性值的一个组件,以包括所分析文件的标准系统运行路径。
-.sp
+.RE
+
 在某些情况下,您可能需要防止自动生成依赖项。例如,如果软件包提供了一个用于导入一组模块的样例 Python 脚本,则该样例脚本导入的那些模块不是提供该样例脚本的软件包的依赖项。使用操作或清单属性 \fBpkg.depend.bypass-generate\fR 可以防止针对指定的文件生成依赖项。
 .sp
-\fBpkg.depend.bypass-generate\fR 值是与文件名匹配的 \fBperl5 \fR 正则表达式。正则表达式隐式固定在文件路径的开头和结尾。以下示例中提供的值与 \fBthis/that\fR 匹配,但与 \fBsomething/this/that/the/other\fR 不匹配。
+\fBpkg.depend.bypass-generate\fR 值是与文件名匹配的 Python 正则表达式。正则表达式隐式固定在文件路径的开头和结尾。以下示例中提供的值与 \fBthis/that\fR 匹配,但与 \fBsomething/this/that/the/other\fR 不匹配。
 .sp
 .in +2
 .nf
@@ -157,29 +216,86 @@
 .fi
 .in -2
 
+有关 Python 正则表达式语法的更多信息,请使用命令 \fBpydoc re\fR 或参见 \fBhttp://docs.python.org/dev/howto/regex.html\fR 中更为完整的文档。
+.sp
+当 \fBpkgdepend generate\fR 输入清单包含 SMF 清单文件时,由这些 SMF 清单文件声明的任何 SMF 服务或实例都将包括在 \fBpkgdepend\fR 输出中。这些 SMF 服务或实例以名称为 \fBorg.opensolaris.smf.fmri\fR 的 \fBset\fR 操作的形式包括在输出中。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgdepend resolve\fR [\fB-moSv\fR] [\fB-d\fR \fIoutput_dir\fR] [\fB-s\fR \fI suffix\fR] \fImanifest_file\fR ...\fR
+.ad
+.sp .6
+.RS 4n
+将文件中的依赖项转换为提供这些文件的软件包中的依赖项。先根据命令行中给定的清单解析依赖项,然后再根据系统上安装的软件包进行解析。缺省情况下,每个清单的依赖项放置在名为 \fB\fImanifest_file\fR.res\fR 的文件中。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-m\fR\fR
+.ad
+.sp .6
+.RS 4n
+将重复清单,删除 \fBgenerate\fR 步骤生成的任何依赖项,然后添加已解析的依赖项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-o\fR\fR
+.ad
+.sp .6
+.RS 4n
+将结果写入到标准输出。该选项旨在供用户使用。将此输出附加到某个文件可能会导致产生无效的清单。在用于清单处理的管道中使用时,强烈建议使用 \fB-d\fR 或 \fB-s\fR 选项,而不要使用 \fB-o\fR。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBresolve [\fB-moSv\fR] [\fB-d\fR \fI output_dir\fR] [\fB-s\fR \fIsuffix\fR] \fI manifest_path\fR ...\fR\fR
+\fB\fB-d\fR \fIoutput_dir\fR\fR
+.ad
+.sp .6
+.RS 4n
+将单独文件中提供的每个清单的已解析依赖项写入 \fIoutput_dir\fR 中。缺省情况下,每个文件与清单(该清单是写入该文件的依赖项的源)具有相同的基名。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIsuffix\fR\fR
 .ad
 .sp .6
 .RS 4n
-将文件中的依赖项转换为提供这些文件的软件包中的依赖项。先根据命令行中给定的清单解析依赖项,然后再根据系统上安装的软件包进行解析。缺省情况下,每个清单的依赖项放置在名为 \fB\fI manifest_path\fR.res\fR 的文件中。
-.sp
-与 \fB-m\fR 一起使用时,将重复清单,删除 \fBgenerate\fR 步骤生成的任何依赖项,然后添加已解析的依赖项。
-.sp
-与 \fB-o\fR 一起使用时,会将结果写入到标准输出。该选项旨在供用户使用。将此输出附加到某个文件可能会导致产生无效的清单。在用于清单处理的管道中使用时,强烈建议使用 \fB-d\fR 或 \fB-s\fR 选项,而不要使用 \fB-o\fR。
+对于每个输出文件,将 \fIsuffix\fR 附加到文件(该文件是解析的依赖项的源)的基名。如果 \fIsuffix\fR 不是 \fI\&.suffix\fR 格式,则会将句点 (.) 附加到 \fIsuffix\fR 的前面。
+.RE
+
 .sp
-与 \fB-d\fR 一起使用时,会将单独文件中提供的每个清单的已解析依赖项写入 \fIoutput_dir\fR 中。缺省情况下,每个文件与清单(该清单是写入该文件的依赖项的源)具有相同的基名。
-.sp
-与 \fB-s\fR 一起使用时,对于每个输出文件,会将 \fIsuffix\fR 附加到文件(该文件是解析的依赖项的源)的基名。"." 附加到 \fIsuffix\fR 的前面(如果未提供)。
+.ne 2
+.mk
+.na
+\fB\fB-S\fR\fR
+.ad
+.sp .6
+.RS 4n
+只根据命令行上指定的清单进行解析,而不根据系统上安装的清单进行解析。
+.RE
+
 .sp
-与 \fB-S\fR 一起使用时,只根据命令行上指定的清单进行解析,而不根据系统上安装的清单进行解析。
-.sp
-与 \fB-v\fR 一起使用时,将包括其他软件包依赖项调试元数据。
+.ne 2
+.mk
+.na
+\fB\fB-v\fR\fR
+.ad
+.sp .6
+.RS 4n
+将包括其他软件包依赖项调试元数据。
+.RE
+
 .RE
 
 .SH 示例
@@ -187,7 +303,7 @@
 \fB示例 1 \fR生成依赖项
 .sp
 .LP
-为 \fBfoo\fR 中写入的清单(其内容目录在 \fB\&./bar/baz\fR 中)生成 赖项,并将结果存储在 \fBfoo fdeps\fR 中。
+为 \fBfoo\fR 中写入的清单(其内容目录在 \fB\&./bar/baz\fR 中)生成依赖项,并将结果存储在 \fBfoo fdeps\fR 中。
 
 .sp
 .in +2
@@ -284,10 +400,10 @@
 # Add runpath and bypass-generate attributes:
 #
 file NOHASH path=opt/python/foo/file.py mode=0644 group=sys owner=root \e
-    pkg.depend.bypass-generate=^.*/test.py.*$ \e
-    pkg.depend.bypass-generate=^.*/testmodule.so$ \e
-    pkg.depend.bypass-generate=^.*/test.so$ \e
-    pkg.depend.bypass-generate=^usr/lib/python2.6/vendor-packages/xdg/.*$ \e
+    pkg.depend.bypass-generate=.*/test.py.* \e
+    pkg.depend.bypass-generate=.*/testmodule.so \e
+    pkg.depend.bypass-generate=.*/test.so \e
+    pkg.depend.bypass-generate=usr/lib/python2.6/vendor-packages/xdg/.* \e
     pkg.depend.runpath=$PKGDEPEND_RUNPATH:/opt/python
 
 $ \fBpkgdepend generate -d proto manifest.py\fR
--- a/src/man/zh_CN/pkgdiff.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgdiff.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgdiff 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgdiff 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgdiff \- 比较软件包清单
 .SH 用法概要
@@ -23,8 +23,8 @@
 .na
 \fB+ \fIcomplete_action\fR\fR
 .ad
-.RS 21n
-.rt  
+.sp .6
+.RS 4n
 此操作在 \fIfile2\fR 中而不在 \fIfile1\fR 中。
 .RE
 
@@ -34,8 +34,8 @@
 .na
 \fB- \fIcomplete_action\fR\fR
 .ad
-.RS 21n
-.rt  
+.sp .6
+.RS 4n
 此操作在 \fIfile1\fR 中而不在 \fIfile2\fR 中。
 .RE
 
@@ -52,8 +52,8 @@
 .na
 \fB- \fIattribute1\fR=\fIvalue1\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 此 \fIattribute\fR,\fIvalue\fR 在 \fIfile1\fR 中而不在 \fIfile2\fR 中。
 .RE
 
@@ -63,8 +63,8 @@
 .na
 \fB+ \fIattribute2\fR=\fIvalue2\fR\fR
 .ad
-.RS 23n
-.rt  
+.sp .6
+.RS 4n
 此 \fIattribute\fR,\fIvalue\fR 在 \fIfile2\fR 中而不在 \fIfile1\fR 中。
 .RE
 
@@ -79,10 +79,21 @@
 .ne 2
 .mk
 .na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-i\fR \fIattribute\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 比较期间将忽略 \fIattribute\fR(如果存在)。可以使用 \fB-i\fR\fI hash\fR 忽略文件散列值。该选项不能与 \fB-o\fR 选项一起使用。可以重复该选项。
 .RE
 
@@ -92,8 +103,8 @@
 .na
 \fB\fB-o\fR \fIattribute\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 仅报告 \fIattribute\fR 的差异。该选项不能与 \fB-i\fR 选项一起使用。该选项会省略不影响操作 \fIattribute\fR 的任何操作更改。
 .RE
 
@@ -103,8 +114,8 @@
 .na
 \fB\fB-v\fR \fIname\fR=\fI value\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 仅计算该变体值的差异。例如,只计算 \fBarch=sparc\fR 的差异。在进行比较之前,将删除所有操作的该变体标记。只能为每个变体指定一个值。可对不同的变体重复该选项。
 .RE
 
--- a/src/man/zh_CN/pkgfmt.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgfmt.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgfmt 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgfmt 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgfmt \- 格式化软件包清单
 .SH 用法概要
@@ -27,9 +27,24 @@
 .ne 2
 .mk
 .na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.RS 10n
+.rt  
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-c\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 检查清单是否格式化为 \fBpkgfmt\fR 样式。
 .RE
@@ -40,7 +55,7 @@
 .na
 \fB\fB-d\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 以统一格式显示与格式化版本的清单差异。
 .RE
@@ -51,7 +66,7 @@
 .na
 \fB\fB-u\fR\fR
 .ad
-.RS 6n
+.RS 10n
 .rt  
 达到 80 个字符时不自动换行。将传统的文本处理工具应用到软件包清单时,该选项十分有用。
 .RE
--- a/src/man/zh_CN/pkglint.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkglint.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,14 +1,14 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkglint 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkglint 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkglint \- 映像包管理系统软件包 lint
 .SH 用法概要
 .LP
 .nf
-/usr/bin/pkglint [-c \fIdir\fR] [-r \fIuri\fR] [-p \fIregexp\fR]
-    [-f \fIrcfile\fR] [-b \fIbuild_no\fR] [-v]
-    [-l \fIuri\fR] | \fImanifest\fR ...
+/usr/bin/pkglint [-c \fIcache_dir\fR] [-r \fIrepo_uri\fR] [-p \fIregexp\fR]
+    [-f \fIconfig_file\fR] [-b \fIbuild_no\fR] [-v]
+    [-l \fIlint_uri\fR] | \fImanifest\fR ...
 .fi
 
 .LP
@@ -22,7 +22,7 @@
 \fBpkglint\fR 对一个或多个软件包清单运行一系列检查,并有选择性地引用其他系统信息库。
 .sp
 .LP
-在发布软件包之前,应该在软件包构建期间使用 \fBpkglint\fR。\fBpkglint\fR 将对清单执行全面的测试,在正常操作 \fBpkgsend\fR(1) 或 \fBpkg.depotd\fR(1M) 期间,执行这种测试可能会消耗过多的资源。\fB pkglint\fR 检查包括对重复操作、缺少的属性和非常规文件权限进行测试。
+应该在发布软件包之前,在软件包构建期间使用 \fBpkglint\fR。\fBpkglint\fR 将对清单执行全面的测试,在 \fBpkgsend\fR 或 \fBpkg.depotd\fR 正常操作期间,执行这种测试可能会消耗过多的资源。\fB pkglint\fR 检查包括对重复操作、缺少的属性和非正常文件权限的测试。
 .sp
 .LP
 可以在命令行上将用于 lint 的清单作为本地文件的空格分隔列表进行传递,也可以从系统信息库检索清单。
@@ -34,7 +34,7 @@
 \fBpkglint\fR 的后续调用可以重新使用高速缓存目录,并可以省略任何 \fB-r\fR 或 \fB-l\fR 参数。
 .sp
 .LP
-\fBpkglint\fR 对在高速缓存目录中配置发布者提供有限的支持。使用 \fBpkg\fR(1) 可对这些映像执行更复杂的发布者配置。
+\fBpkglint\fR 对在高速缓存目录中配置发布者提供有限的支持。使用 \fBpkg\fR 可对这些映像执行更复杂的发布者配置。
 .sp
 .LP
 \fBpkglint\fR 使软件包作者能够绕过对给定清单或操作进行的检查。其中的属性 \fB pkg.linted\fR 设置为 \fBTrue\fR 的清单或操作不会为该清单或操作生成任何 lint 输出。
@@ -55,10 +55,25 @@
 .ne 2
 .mk
 .na
+\fB\fB-h\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-b\fR \fIbuild_no\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 指定内部版本号,用于细化从 lint 和引用系统信息库执行 lint 期间使用的软件包列表。如果不指定 \fB-b\fR 选项,将使用最新版本的软件包。另请参见 \fBversion.pattern \fR 配置属性。
 .RE
 
@@ -68,8 +83,8 @@
 .na
 \fB\fB-c\fR \fIcache_dir\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 指定用于从 lint 和引用系统信息库高速缓存软件包元数据的本地目录。
 .RE
 
@@ -79,8 +94,8 @@
 .na
 \fB\fB-l\fR \fIlint_uri\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 指定表示 lint 系统信息库位置的 URI。支持基于 HTTP 和基于文件系统的发布。如果指定 \fB- l\fR,则还必须指定 \fB-c\fR。
 .RE
 
@@ -90,8 +105,8 @@
 .na
 \fB\fB-L\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 列出已知的和排除的 lint 检查,然后退出。显示每个检查的短名称和描述。与 \fB-v\fR 标志结合使用时,将显示实现检查的方法而不显示描述。
 .RE
 
@@ -101,8 +116,8 @@
 .na
 \fB\fB-f\fR \fIconfig_file\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 使用 \fI config_file\fR 配置文件来配置 \fBpkglint\fR 会话。
 .RE
 
@@ -112,9 +127,9 @@
 .na
 \fB\fB-p\fR \fIregexp\fR\fR
 .ad
-.RS 18n
-.rt  
-指定正则表达式,用于细化要从 lint 系统信息库检查的软件包列表。将会加载来自引用系统信息库的所有清单(假定它们与提供的 \fB-b\fR 值匹配),并忽略此模式。
+.sp .6
+.RS 4n
+指定正则表达式,用于细化要从 lint 系统信息库检查的软件包列表。将会装入来自引用系统信息库的所有清单(假定它们与提供的 \fB-b\fR 值匹配),并忽略此模式。
 .RE
 
 .sp
@@ -123,8 +138,8 @@
 .na
 \fB\fB-r\fR \fIrepo_uri\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 指定表示引用系统信息库位置的 URI。如果指定 \fB-r\fR,则还必须指定 \fB-c\fR。
 .RE
 
@@ -134,22 +149,11 @@
 .na
 \fB\fB-v\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 以详细模式运行 \fBpkglint\fR,覆盖配置文件中的任何 \fBlog_level\fR 设置。
 .RE
 
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR 或 \fB-?\fR\fR
-.ad
-.RS 18n
-.rt  
-显示用法消息。
-.RE
-
 .SH 文件
 .sp
 .LP
@@ -160,8 +164,8 @@
 .na
 \fB\fBlog_level\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 发出 lint 消息的最低级别。低于该级别的 lint 消息将被放弃。缺省值为 \fBINFO\fR。
 .sp
 严重性从低到高的日志级别依次为 \fBDEBUG\fR、\fB INFO\fR、\fBWARNING\fR、\fBERROR\fR 和 \fB CRITICAL\fR。
@@ -173,8 +177,8 @@
 .na
 \fB\fBdo_pub_checks\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBTrue\fR,则执行可能只对已发布的软件包有意义的检查。缺省值为 \fBTrue\fR。
 .RE
 
@@ -184,9 +188,9 @@
 .na
 \fB\fBpkglint.ext.\fR*\fR
 .ad
-.RS 24n
-.rt  
-\fBpkglint\fR 的插件机制允许在运行时添加其他 lint 模块。以 \fB pkglint.ext.\fR 开头的任何键采用必须是完全指定的 Python 模块的值。有关更多信息,请参见"开发者"一节。
+.sp .6
+.RS 4n
+\fBpkglint\fR 的插件机制允许在运行时添加其他 lint 模块。以 \fB pkglint.ext.\fR 开头的任何键采用必须是完全指定的 Python 模块的值。有关更多信息,请参见“开发工具”一节。
 .RE
 
 .sp
@@ -195,8 +199,8 @@
 .na
 \fB\fBpkglint.exclude\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 要从执行的检查集中省略的完全指定的 Python 模块、类或函数名称的空格分隔列表。
 .RE
 
@@ -206,8 +210,8 @@
 .na
 \fB\fBuse_progress_tracker\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 如果为 \fBTrue\fR,则在 lint 运行期间迭代清单时,会使用进度跟踪器。缺省值为 \fBTrue\fR。
 .RE
 
@@ -217,12 +221,12 @@
 .na
 \fB\fBversion.pattern\fR\fR
 .ad
-.RS 24n
-.rt  
+.sp .6
+.RS 4n
 指定内部版本号以针对 (\fB-b\fR) 执行 lint 时使用的版本模式。如果未在配置文件中指定,则 \fB-b\fR 选项将使用模式 \fB*,5.11-0.\fR,并使用分支前缀 0 来匹配 5.11 内部版本的所有组件。
 .RE
 
-.SH 开发者
+.SH 开发工具
 .sp
 .LP
 扩展 \fBpkglint\fR、子类 \fBpkg.lint.base.Checker\fR 及其子类 \fBManifestChecker \fR、\fBActionChecker\fR 和 \fBContentChecker\fR 执行的检查集。将包含这些类的 Python 模块名称添加到配置文件中的新 \fBpkglint.ext.\fR 键。
--- a/src/man/zh_CN/pkgmerge.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgmerge.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgmerge 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgmerge 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgmerge \- 映像包管理系统软件包合并实用程序
 .SH 用法概要
@@ -29,11 +29,26 @@
 .ne 2
 .mk
 .na
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-d\fR \fIdest_repo\fR\fR
 .ad
 .sp .6
 .RS 4n
-要将合并软件包发布到的目标系统信息库的文件系统路径或 URI。目标系统信息库必须已存在。可以使用 \fBpkgrepo\fR(1) 创建新的系统信息库。
+指定要将合并软件包发布到的目标系统信息库的文件系统路径或 URI。目标系统信息库必须已存在。可以使用 \fBpkgrepo\fR 创建新的系统信息库。
 .RE
 
 .sp
@@ -55,18 +70,7 @@
 .ad
 .sp .6
 .RS 4n
-用于该源中软件包的变量名称和值,后跟要从中检索软件包的源系统信息库或软件包归档文件的文件系统路径或 URI。可指定多个变量,以逗号分隔。必须为所有源命名相同的变量。可以多次指定此选项。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR 或 \fB-?\fR\fR
-.ad
-.sp .6
-.RS 4n
-显示用法消息。
+指定用于该源的软件包的变量名称和值,后跟要从中检索软件包的源系统信息库或软件包归档文件的文件系统路径或 URI。可指定多个变量,以逗号分隔。必须为所有源命名相同的变量。可以多次指定此选项。
 .RE
 
 .SH 环境变量
--- a/src/man/zh_CN/pkgmogrify.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgmogrify.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgmogrify 1 "2011 年 8 月 30 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgmogrify 1 "2012 年 6 月 4 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgmogrify \- 映像包管理系统清单变换程序
 .SH 用法概要
@@ -44,11 +44,26 @@
 .ne 2
 .mk
 .na
-\fB\fB-D\fR \fIname\fR=\fI value\fR\fR
+\fB\fB-?\fR\fR
+.ad
+.br
+.na
+\fB\fB--help\fR\fR
 .ad
 .sp .6
 .RS 4n
-将 \fIname\fR 定义为一个宏,其值为 \fIvalue\fR。宏在输入文件中显示为 \fB $(macro)\fR。将重复执行替换操作,直到再也找不到变换。常见用语包括:
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-D\fR \fImacro\fR=\fI value\fR\fR
+.ad
+.sp .6
+.RS 4n
+将 \fImacro\fR 定义为一个宏,其值为 \fIvalue\fR。宏在输入文件中显示为 \fB $(macro)\fR。将重复执行替换操作,直到再也找不到变换。常见用语包括:
 .RS +4
 .TP
 .ie t \(bu
@@ -83,11 +98,11 @@
 .ne 2
 .mk
 .na
-\fB\fB-I\fR \fIinclude_directory\fR\fR
+\fB\fB-I\fR \fIincludedir\fR\fR
 .ad
 .sp .6
 .RS 4n
-将指定目录添加到在命令行中和在嵌入式 include 指令中指定的文件的搜索路径中。
+将指定目录添加到在命令行和在嵌入式 include 指令中指定的文件的搜索路径中。
 .RE
 
 .sp
@@ -134,17 +149,6 @@
 将注释写入显示变换效果的输出清单。该信息可以帮助调试。
 .RE
 
-.sp
-.ne 2
-.mk
-.na
-\fB\fB--help\fR 或 \fB-?\fR\fR
-.ad
-.sp .6
-.RS 4n
-显示用法消息。
-.RE
-
 .SH 嵌入式指令
 .sp
 .LP
@@ -181,13 +185,13 @@
 .sp
 .in +2
 .nf
-[\fIaction-type\fR ... ] [\fIattribute\fR=<\fIvalue-regexp\fR> ...]
+[\fIaction-name\fR ... ] [\fIattribute\fR=<\fIvalue-regexp\fR> ...]
 .fi
 .in -2
 
 .sp
 .LP
-必须匹配其中一个指定的 \fIaction-types\fR。必须匹配所有指定的 \fIattributes\fR。使用的正则表达式语法是 Python 语法。有关 Python 正则表达式语法的更多信息,请使用命令 \fBpydoc re\fR 或参见 \fBhttp://docs.python.org/dev/howto/regex.html \fR 中的更完整文档。该正则表达式固定于开头而非结尾。因此,通过文件扩展名进行匹配的正则表达式匹配文件必须包含前导 \fB\&.*\fR,且应当包含尾随 \fB $\fR。
+必须至少匹配一个指定的 \fIaction-name\fR。必须匹配指定的每个 \fIattribute\fR。操作名称和属性列在 \fBpkg\fR(5) 手册页的“操作”中。使用的正则表达式语法是 Python 语法。有关 Python 正则表达式语法的更多信息,请使用命令 \fBpydoc re\fR 或请参见 \fBhttp://docs.python.org/dev/howto/regex.html \fR 中更为完整的文档。该正则表达式固定于开头而非结尾。因此,通过文件扩展名进行匹配的正则表达式匹配文件必须包含前导 \fB\&.*\fR,且应当包含尾随 \fB $\fR。
 .sp
 .LP
 可以指定多个条件,以空格分隔。
@@ -316,7 +320,7 @@
 .RE
 .sp
 .LP
-以下三个合成属性类似于 \fBpkg\fR(1) 中使用的属性:
+以下三个合成属性类似于 \fBpkg\fR 中使用的属性:
 .RS +4
 .TP
 .ie t \(bu
@@ -333,7 +337,7 @@
 .TP
 .ie t \(bu
 .el o
-\fBaction.name\fR 引用操作类型的名称。
+\fBaction.name\fR 引用操作的名称。
 .RE
 .sp
 .LP
@@ -349,7 +353,7 @@
 这不仅在将软件包属性视为操作属性来引用方面,而且在匹配甚至暂时修改这些属性方面,都很有用。因此,在这些情况下都可以使用合成属性名称 \fBpkg\fR(仅在 \fBpkgmogrify\fR 上下文中)。
 .sp
 .LP
-如果 \fBpkgmogrify\fR 完成读取在命令行中指定的清单并且该清单定义了 \fBpkg.fmri\fR 软件包属性,\fBpkgmogrify\fR 会创建此合成 \fBpkg\fR 操作,其属性为软件包的属性。\fB<transform>\fR 指令随后会对此操作进行匹配(正如任何其他操作类型一样)。
+如果 \fBpkgmogrify\fR 完成读取在命令行中指定的清单并且该清单定义了 \fBpkg.fmri\fR 软件包属性,\fBpkgmogrify\fR 会创建此合成 \fBpkg\fR 操作,其属性为软件包的属性。\fB<transform>\fR 指令随后会对此操作进行匹配,正如它会对任何其他操作进行匹配一样。
 .sp
 .LP
 \fBpkg\fR 操作中的操作是特殊的,它们仅在内存中进行,不会直接影响发出的清单。例如,尝试通过 \fBadd\fR、\fBdefault\fR 或 \fBset\fR 操作设置 \fBpkg\fR 操作的属性时,不会使 \fBset\fR 操作添加到清单中,虽然该操作将可用于其他 \fB<transform>\fR 指令进行匹配。尝试 \fBemit\fR\fBpkg\fR 操作会导致错误。要添加软件包属性,改为 \fBemit\fR\fBset \fR 操作。
@@ -434,7 +438,7 @@
 \fB示例 4 \fR将 FMRI 属性转换为 Depend 操作
 .sp
 .LP
-将软件包属性 \fBpkg.fmri\fR 转换为 \fBdepend\fR 操作,使其成为集合的一部分。
+将软件包属性 \fBpkg.fmri\fR 转换为 \fBdepend\fR 操作,使其成为 incorporation 的一部分。
 
 .sp
 .in +2
@@ -493,7 +497,7 @@
 \fB示例 8 \fR将依赖项添加到未标记为已过时的软件包中
 .sp
 .LP
-对于未标记为已过时的任何软件包,为提供软件包的合并添加集合的依赖项。必须在读入清单后执行该组变换,否则始终发出依赖项。因为修改 \fBpkg\fR 操作不会永久起作用,所以无需清除匹配 \fB pkg.obsolete=false\fR 的属性。
+对于未标记为已过时的任何软件包,为提供软件包的合并添加对 incorporation 的依赖。必须在读入清单后执行该组变换,否则始终发出依赖项。因为修改 \fBpkg\fR 操作不会永久起作用,所以无需清除匹配 \fB pkg.obsolete=false\fR 的属性。
 
 .sp
 .in +2
@@ -587,8 +591,8 @@
 .na
 \fB\fB/usr/share/pkg/transforms\fR\fR
 .ad
-.RS 29n
-.rt  
+.sp .6
+.RS 4n
 该目录包含使用有用变换设置侧面、执行器和其他属性的文件。
 .RE
 
--- a/src/man/zh_CN/pkgrecv.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgrecv.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgrecv 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgrecv 1 "2012 年 6 月 11 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgrecv \- 映像包管理系统内容检索实用程序
 .SH 用法概要
@@ -19,7 +19,10 @@
 .SH 描述
 .sp
 .LP
-\fBpkgrecv\fR 允许用户检索 \fBpkg\fR(5) 系统信息库或软件包归档文件中的软件包。\fBpkgrecv\fR 还可以选择性地将检索到的软件包重新发布到另一个软件包系统信息库中或者对其进行归档。缺省情况下,会以 \fBpkg\fR(1)、\fBpkg.depotd\fR(1M) 以及软件包发布工具可使用的软件包系统信息库格式检索软件包。
+\fBpkgrecv\fR 允许用户检索 \fBpkg\fR(5) 系统信息库或软件包归档文件中的软件包。\fBpkgrecv\fR 还可以选择性地将检索到的软件包重新发布到另一个软件包系统信息库中或者对其进行归档。缺省情况下,会以 \fBpkg\fR、\fBpkg.depotd\fR 以及软件包发布工具可使用的软件包系统信息库格式检索软件包。
+.sp
+.LP
+完成 \fBpkgrecv\fR 操作后,在系统信息库上运行 \fBpkgrepo refresh\fR 或 \fBpkgrepo rebuild\fR 以构建搜索索引。
 .SH 选项
 .sp
 .LP
@@ -28,10 +31,21 @@
 .ne 2
 .mk
 .na
+\fB\fB-h\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB-a\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 将检索的软件包数据存储在 \fB-d\fR 指定的位置中的 \fBpkg\fR(5) 归档文件中。该文件不能已存在。此选项仅可以与基于文件系统的目标一起使用。尽管不要求,但还是强烈建议使用文件扩展名 \fB\&.p5p\fR(例如:\fB archive.p5p\fR)。该选项不能与 \fB--raw\fR 结合使用。
 .RE
 
@@ -41,31 +55,20 @@
 .na
 \fB\fB-c\fR \fIcache_dir\fR\fR
 .ad
-.RS 19n
-.rt  
-将用于缓存已下载内容的目录的路径。如果没有提供此目录,客户机将自动选择一个高速缓存目录。如果下载中断并且已自动选择了一个高速缓存目录,可使用该选项继续执行下载。有关如何设置用于存储临时数据的位置的详细信息,请参见下面的"环境变量"部分。
+.sp .6
+.RS 4n
+指定将用于缓存已下载内容的目录的路径。如果没有提供此目录,客户机将自动选择一个高速缓存目录。如果下载中断并且已自动选择了一个高速缓存目录,可使用该选项继续执行下载。有关如何设置用于存储临时数据的位置的详细信息,请参见下文的“环境变量”部分。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-d\fR \fIpath_or_uri\fR\fR
+\fB\fB-d\fR (\fIpath\fR|\fI dest_uri\fR)\fR
 .ad
-.RS 19n
-.rt  
-要将软件包重新发布到的目标的文件系统路径或 URI。该目标必须已存在。可以使用 \fB pkgrepo\fR(1) 创建新的系统信息库。如果指定了 \fB-a\fR,则会假定目标为新的软件包归档文件。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fB-h\fR\fR
-.ad
-.RS 19n
-.rt  
-显示用法消息。
+.sp .6
+.RS 4n
+指定要将软件包重新发布到的目标的文件系统路径或 URI。如果指定了 \fB-a\fR,则目标为尚不存在的新软件包归档文件。否则,目标必须是已存在的软件包系统信息库。可以使用 \fBpkgrepo\fR 创建新的系统信息库。
 .RE
 
 .sp
@@ -74,9 +77,9 @@
 .na
 \fB\fB-k\fR\fR
 .ad
-.RS 19n
-.rt  
-使检索的软件包内容保持压缩状态。重新发布时会忽略该选项。压缩的软件包内容不得与 \fBpkgsend\fR(1) 一起使用。
+.sp .6
+.RS 4n
+使检索的软件包内容保持压缩状态。重新发布时会忽略该选项。压缩的软件包内容不得与 \fBpkgsend\fR 一起使用。
 .RE
 
 .sp
@@ -85,8 +88,8 @@
 .na
 \fB\fB-m\fR \fImatch\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 使用以下值控制匹配行为:
 .sp
 .ne 2
@@ -94,8 +97,8 @@
 .na
 \fB\fBall-timestamps\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 包括所有匹配的时间戳,而不仅仅是最新的时间戳(意味着 \fB all-versions\fR)。
 .RE
 
@@ -105,8 +108,8 @@
 .na
 \fB\fBall-versions\fR\fR
 .ad
-.RS 18n
-.rt  
+.sp .6
+.RS 4n
 包括所有匹配的版本,而不仅仅是最新的版本。
 .RE
 
@@ -118,8 +121,8 @@
 .na
 \fB\fB-n\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 执行试运行,不进行任何更改。
 .RE
 
@@ -129,8 +132,8 @@
 .na
 \fB\fB-r\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 递归检索提供的软件包列表的所有依赖项。
 .RE
 
@@ -138,21 +141,21 @@
 .ne 2
 .mk
 .na
-\fB\fB-s\fR \fIsrc_repo_uri\fR\fR
+\fB\fB-s\fR \fIsrc_uri\fR\fR
 .ad
-.RS 19n
-.rt  
-URI 代表要从中接收软件包数据的 \fBpkg\fR(5) 系统信息库或软件包归档文件的位置。
+.sp .6
+.RS 4n
+指定一个 URI,代表要从中接收软件包数据的 \fBpkg\fR(5) 系统信息库或软件包归档文件的位置。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB--cert\fR \fIfile\fR\fR
+\fB\fB--cert\fR \fIcertfile\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 指定用于从 HTTPS 系统信息库进行软件包检索的客户机 SSL 证书文件。
 .RE
 
@@ -160,10 +163,10 @@
 .ne 2
 .mk
 .na
-\fB\fB--key\fR \fIfile\fR\fR
+\fB\fB--key\fR \fIkeyfile\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 指定用于从 HTTPS 系统信息库进行软件包检索的客户机 SSL 密钥文件。
 .RE
 
@@ -173,8 +176,8 @@
 .na
 \fB\fB--newest\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 列出指定系统信息库中提供的最新版本的软件包,然后退出。(忽略 \fB-s\fR 以外的所有其他选项。)
 .RE
 
@@ -184,8 +187,8 @@
 .na
 \fB\fB--raw\fR\fR
 .ad
-.RS 19n
-.rt  
+.sp .6
+.RS 4n
 按主干和版本,检索一组目录结构中的原始软件包数据并将其存储在 \fB-d\fR 指定的位置中。此选项仅可以与基于文件系统的目标一起使用。此软件包数据可用于方便地修改和重新发布软件包,也许通过更正文件内容,也许通过提供附加的软件包元数据。该选项不能与 \fB-a\fR 结合使用。
 .RE
 
@@ -200,10 +203,9 @@
 .in +2
 .nf
 $ \fBpkgrecv -s http://test --newest\fR
-pkg:/[email protected],5.11-0.79:20080221T125720Z
-pkg:/[email protected],5.11-0.79:20080221T123955Z
-pkg:/[email protected],5.11-0.79:20080221T125728Z
-pkg:/[email protected],5.11-0.79:20080221T125730Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z
+pkg://solaris/system/library/[email protected],5.11-0.175.1.0.0.7.1234:20120109T215840Z
+pkg://solaris/system/library/[email protected],5.11-0.175.0.0.0.2.1:20120921T190432Z
 .fi
 .in -2
 .sp
@@ -212,17 +214,20 @@
 \fB示例 2 \fR检索原始软件包数据
 .sp
 .LP
-以 \fBpkgsend include\fR 可以使用的格式接收示例 1 中的 \fBSUNWlibC\fR、\fBSUNWfreetype\fR 和 \fBSUNWlibm\fR 软件包。
+以能够与 \fBpkgsend publish\fR 结合使用的合适格式从示例 1 中接收 \fBc++-runtime\fR 软件包。
 
 .sp
 .in +2
 .nf
 $ \fBpkgrecv -s http://test \e\fR
-\[email protected],5.11-0.79:20080221T125720Z --raw\fR
[email protected],5.11-0.79:20080221T123955Z
[email protected],5.11-0.79:20080221T125728Z
-$ \fBls -d SUNW*\fR
-SUNWfreetype2  SUNWlibC       SUNWlibm
+\fB-d /local/repo --raw \e\fR
+\[email protected],5.11-0.175.0.0.0.2.1:20120921T190358Z\fR
+Processing packages for publisher solaris ...
+Retrieving and evaluating 1 package(s)...
+PROCESS       ITEMS     GET (MB)    SEND (MB)
+Completed       1/1      3.5/3.5      0.0/0.0
+$ \fBls /local/repo\fR
+pkg5.repository  publisher  system%2Flibrary%2Fc%2B%2B-runtime
 .fi
 .in -2
 .sp
@@ -231,12 +236,12 @@
 \fB示例 3 \fR从系统中检索依赖项
 .sp
 .LP
-从名为 \fBtest\fR 的系统中接收软件包 \fBSUNWvim\fR 及其所有依赖项。
+从名为 \fBtest\fR 的系统中接收软件包 \fBeditor/vim\fR 及其所有依赖项。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -r SUNWvim\fR
+$ \fBpkgrecv -s http://test -d /local/repo -r editor/vim\fR
 .fi
 .in -2
 .sp
@@ -245,88 +250,97 @@
 \fB示例 4 \fR检索所有版本
 .sp
 .LP
-从名为 \fBtest\fR 的系统中接收软件包 \fBSUNWvim\fR 的所有版本。
+从名为 \fBtest\fR 的系统中接收软件包 \fBeditor/vim\fR 的所有版本。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -m all-versions SUNWvim\fR
+$ \fBpkgrecv -s http://test -d /local/repo -m all-versions \e\fR
+\fBeditor/vim\fR
+Processing packages for publisher solaris ...
+Retrieving and evaluating 2 package(s)...
+PROCESS       ITEMS     GET (MB)    SEND(MB)
+Completed       2/2    16.7/16.7    44.9/44.9
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 5 \fR检索所有版本并本地重新发布
+\fB示例 5 \fR检索所有版本并远程重新发布
 .sp
 .LP
-从名为 \fBtest\fR 的系统中接收软件包 \fBSUNWvim\fR 的所有版本,然后将其重新发布到本地系统信息库中。
+从名为 \fBtest\fR 的系统中接收软件包 \fBlibrary/zlib\fR 的所有版本,然后将其重新发布到名为 \fBremote\fR 的系统上的远程系统信息库中。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -d /local/repo SUNWvim\fR
+$ \fBpkgrecv -s http://test -d http://remote:10000 \e\fR
+\fB-m all-versions library/zlib\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 6 \fR检索所有版本并远程重新发布
+\fB示例 6 \fR从系统信息库中检索依赖项
 .sp
 .LP
-从名为 \fBtest\fR 的系统中接收软件包 \fBSUNWzlib\fR 的所有版本,然后将其重新发布到名为 \fBremote\fR 的系统上的远程系统信息库中。
+从位于 \fB/export/repo\fR 的系统信息库中接收软件包 \fBeditor/gnu-emacs\fR 及其所有依赖项。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://test -d http://remote:10000 SUNWzlib\fR
+$ \fBpkgrecv -s /export/repo -d /local/repo -r editor/gnu-emacs\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 7 \fR从系统信息库中检索依赖项
+\fB示例 7 \fR检索其他软件包和更改的内容
 .sp
 .LP
-从位于 \fB/export/repo\fR 的系统信息库中接收软件包 \fBSUNWemacs\fR 及其所有依赖项。
+从位于 \fBhttp://pkg.oracle.com/solaris/release/\fR 的系统信息库中将并非已存在的所有软件包和所有已更改内容接收到位于 \fB/export/repoSolaris11\fR 的系统信息库。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s /export/repo -r SUNWemacs\fR
+$ \fBpkgrecv -s http://pkg.oracle.com/solaris/release/ \e\fR
+\fB-d /export/repoSolaris11 -m all-timestamps '*'\fR
+.fi
+.in -2
+.sp
+
+.sp
+.LP
+将位于 \fBhttp://pkg.oracle.com/solaris/support/ \fR的安全系统信息库中的所有尚不存在的软件包和所有更改内容接收到位于 \fB/export/repoSolaris11\fR 的系统信息库。
+
+.sp
+.in +2
+.nf
+$ \fBpkgrecv -s http://pkg.oracle.com/solaris/support/ \e\fR
+\fB-d /export/repoSolaris11 -m all-timestamps \e\fR
+\fB--key /var/pkg/ssl/Oracle_Solaris_11_Support.key.pem \e\fR
+\fB--cert /var/pkg/ssl/Oracle_Solaris_11_Support.certificate.pem '*'\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 8 \fR检索其他软件包
+\fB示例 8 \fR创建软件包归档文件
 .sp
 .LP
-从位于 \fBhttp://example.com:10000\fR 的系统信息库中接收并非已存在的所有软件包。
+根据位于 \fBhttp://example.com:10000 \fR 的系统信息库创建包含软件包 \fBeditor/gnu-emacs\fR 及其所有依赖项的软件包归档文件。
 
 .sp
 .in +2
 .nf
-$ \fBpkgrecv -s http://example.com:10000 -d /my/pkg/repo '*'\fR
+$ \fBpkgrecv -s http://example.com:10000 -d /my/emacs.p5p -a \e\fR
+\fB-r editor/gnu-emacs\fR
 .fi
 .in -2
 .sp
 
 .LP
-\fB示例 9 \fR创建软件包归档文件
-.sp
-.LP
-从位于 \fBhttp://example.com:10000 \fR 的系统信息库中创建包含软件包 \fBSUNWemacs\fR 及其所有依赖项的软件包归档文件。
-
-.sp
-.in +2
-.nf
-$ \fBpkgrecv -s http://example.com:10000 -d /my/emacs.p5p -a -r SUNWemacs\fR
-.fi
-.in -2
-.sp
-
-.LP
-\fB示例 10 \fR将软件包从归档文件复制到系统信息库中
+\fB示例 9 \fR将软件包从归档文件复制到系统信息库中
 .sp
 .LP
 将软件包归档文件中的所有软件包复制到位于 \fB/export/repo\fR 中的现有系统信息库。
--- a/src/man/zh_CN/pkgrepo.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgrepo.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgrepo 1 "2011 年 8 月 30日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkgrepo 1 "2012 年 6 月 22 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgrepo \- 映像包管理系统的系统信息库管理实用程序
 .SH 用法概要
@@ -16,7 +16,7 @@
 
 .LP
 .nf
-/usr/bin/pkgrepo get [-F \fIformat\fR] [-p \fIpublisher\fR ...]
+/usr/bin/pkgrepo get [-F \fIformat\fR] [-H] [-p \fIpublisher\fR ...]
     -s \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]
 .fi
 
@@ -53,7 +53,12 @@
 .LP
 .nf
 /usr/bin/pkgrepo set [-p \fIpublisher\fR] -s \fIrepo_uri_or_path\fR
-    \fIsection/property\fR=[\fIvalue\fR] ... or
+    \fIsection/property\fR=[\fIvalue\fR]
+.fi
+
+.LP
+.nf
+/usr/bin/pkgrepo set [-p \fIpublisher\fR] -s \fIrepo_uri_or_path\fR
     \fIsection/property\fR=([\fIvalue\fR]) ...
 .fi
 
@@ -70,7 +75,7 @@
 .SH 描述
 .sp
 .LP
-通过 \fBpkgrepo\fR 可以创建和管理 \fB pkg\fR(5) 软件包系统信息库。软件包系统信息库是一组预定义的目录和文件,允许 \fBpkg\fR(1) 和发布客户机(例如 \fBpkgsend \fR(1) 或 \fBpkgrecv\fR(1))存储和检索软件包数据。此外,当需要对软件包系统信息库进行基于网络的访问时,\fBpkg.depotd\fR(1m) 可以提供对该系统信息库的客户机访问权限,以存储和/或检索软件包数据。
+通过 \fBpkgrepo\fR 可以创建和管理 \fB pkg\fR(5) 软件包系统信息库。软件包系统信息库是一组预定义的目录和文件,允许 \fBpkg\fR 和发布客户机(例如 \fBpkgsend \fR 或 \fBpkgrecv\fR)存储和检索软件包数据。此外,当需要对软件包系统信息库进行基于网络的访问时,\fBpkg.depotd\fR 可以提供对该系统信息库的客户机访问权限,以存储和/或检索软件包数据。
 .SH 选项
 .sp
 .LP
@@ -79,10 +84,14 @@
 .ne 2
 .mk
 .na
-\fB\fB--help\fR 或 \fB-?\fR\fR
+\fB\fB-?\fR\fR
 .ad
-.RS 17n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 显示用法消息。
 .RE
 
@@ -94,7 +103,7 @@
 .ne 2
 .mk
 .na
-\fB\fBcreate [\fB--version\fR \fIver\fR] \fI uri_or_path\fR\fR\fR
+\fB\fBpkgrepo create\fR [\fB--version\fR \fI ver\fR] \fIuri_or_path\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -102,22 +111,37 @@
 .sp
 该子命令仅可以与基于文件系统的系统信息库一起使用。
 .sp
-使用 \fB--version\fR,以与指定版本兼容的格式创建系统信息库。缺省情况下,会创建版本为 4 的系统信息库。支持的版本包括:
+.ne 2
+.mk
+.na
+\fB\fB--version\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用与指定版本兼容的格式创建系统信息库。缺省情况下,会创建版本为 4 的系统信息库。支持的版本包括:
 .sp
+.ne 2
+.mk
+.na
+\fB3\fR
+.ad
+.RS 5n
+.rt  
+支持为单个发布者存储软件包,目录版本为 1 ,搜索版本为 1。
+.RE
 
 .sp
-.TS
-tab();
-lw(.33i) lw(5.17i) 
-lw(.33i) lw(5.17i) 
-.
-3T{
-支持为单个发布者存储软件包,目录版本为 1 ,搜索版本为 1。
-T}
-4T{
+.ne 2
+.mk
+.na
+\fB4\fR
+.ad
+.RS 5n
+.rt  
 支持为多个发布者存储软件包,目录版本为 1 ,搜索版本为 1。
-T}
-.TE
+.RE
+
+.RE
 
 .RE
 
@@ -125,7 +149,7 @@
 .ne 2
 .mk
 .na
-\fB\fBadd-publisher \fB-s\fR \fIrepo_uri_or_path \fR \fIpublisher\fR ...\fR\fR
+\fB\fBpkgrepo add-publisher\fR \fB-s\fR \fI repo_uri_or_path\fR \fIpublisher\fR ...\fR
 .ad
 .sp .6
 .RS 4n
@@ -138,7 +162,7 @@
 .ne 2
 .mk
 .na
-\fB\fBget [\fB-F\fR \fIformat\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR [\fIsection/property\fR ...]\fR\fR
+\fB\fBpkgrepo get\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fI section/property\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -152,43 +176,126 @@
 .fi
 .in -2
 
-请参见"示例"部分。
+有关显示发布者和系统信息库属性的示例,请参见“示例”部分。
+.sp
+有关属性列表以及每个属性的用途和值,请参见下文的 \fBset\fR 子命令。
 .sp
-有关可能的属性的列表以及每个属性的用途和值,请参见下面的 \fBset\fR 子命令。
-.sp
-使用 \fB-F\fR,指定备用输出格式。\fIformat\fR 的值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定备用输出格式。\fIformat\fR 的值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
+.RE
+
 .sp
-使用 \fB-H\fR,忽略列表的标题。
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
 .sp
-使用 \fB-p\fR,显示给定发布者的属性信息。特殊值 \fBall\fR 显示所有发布者的属性。可以多次指定此选项。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示给定发布者的属性信息。特殊值 \fBall\fR 显示所有发布者的属性。可以多次指定此选项。
+.RE
+
 .sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBinfo [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR\fR\fR
+\fB\fIsection/property\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示指定属性的值,例如 \fB publisher/prefix\fR 或 \fBrepository/version\fR。有关完整的属性列表,请参见 \fB set\fR 子命令。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo info\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR\fR
 .ad
 .sp .6
 .RS 4n
 显示系统信息库已知的软件包发布者的列表。该列表包括每个发布者的软件包数量、最后一次更新发布者的软件包数据的时间以及发布者的软件包数据的状态(例如当前是否处于正在处理状态)。
 .sp
-使用 \fB-F\fR,指定备用输出格式。\fIformat\fR 的值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
-.sp
-使用 \fB-H\fR,忽略列表的标题。
-.sp
-使用 \fB-p\fR,仅显示给定发布者的数据。如果没有提供该选项,将显示所有发布者的数据。可以多次指定此选项。
-.sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定备用输出格式。\fIformat\fR 的值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fB list [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]\fR\fR
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示给定发布者的数据。如果没有提供该选项,将显示所有发布者的数据。可以多次指定此选项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo list\fR [\fB-F\fR \fI format\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher \fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fI pkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -196,58 +303,166 @@
 .sp
 在缺省输出中,第一列包含软件包发布者的名称。第二列包含软件包的名称。第三列是显示软件包状态的标志。状态列中的 \fBo\fR 值表示软件包已过时。状态列中的 \fBr\fR 值表示已重命名软件包,但格式已过时。第四列包含软件包的发行版本和分支版本。有关发行版本和分支版本的信息,请参见 \fBpkg\fR(5)。
 .sp
-使用 \fB-F\fR,指定备用输出格式。\fIformat\fR 的唯一值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
+.ne 2
+.mk
+.na
+\fB\fB-F\fR \fIformat\fR\fR
+.ad
+.sp .6
+.RS 4n
+指定备用输出格式。\fIformat\fR 的值可以是 \fBtsv\fR(以制表符分隔的值)、\fBjson\fR(单行 JavaScript 对象表示法)或 \fBjson-formatted\fR(格式易于阅读的 JavaScript 对象表示法)。
+.RE
+
 .sp
-使用 \fB-H\fR,忽略列表的标题。
+.ne 2
+.mk
+.na
+\fB\fB-H\fR\fR
+.ad
+.sp .6
+.RS 4n
+在列出时省略标题。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅显示给定发布者的软件包。如果没有提供该选项,将显示所有发布者的软件包。可以多次指定此选项。
+.RE
+
 .sp
-使用 \fB-p\fR,仅显示给定发布者的软件包。如果没有提供该选项,将显示所有发布者的软件包。可以多次指定此选项。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.RE
+
+.RE
+
 .sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB- -no-catalog\fR] [\fB--no-index\fR]\fR
+.ad
+.sp .6
+.RS 4n
+放弃在系统信息库中找到的所有目录、搜索以及其他缓存信息,然后根据系统信息库的当前内容重新创建这些信息。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅针对给定发布者执行操作。如果没有提供该选项或者指定了特定值 \fBall\fR,则对所有发布者执行操作。可以多次指定此选项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrebuild [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR\fR
+\fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
 .RS 4n
-放弃在系统信息库中找到的所有目录、搜索以及其他缓存信息,然后根据系统信息库的当前内容重新创建这些信息。
-.sp
-使用 \fB-p\fR,仅对给定发布者执行操作。如果没有提供该选项或者指定了特定值 \fBall\fR,则对所有发布者执行操作。可以多次指定此选项。
+不重新生成软件包数据。
+.RE
+
 .sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
-.sp
-使用 \fB--no-catalog\fR,不重新生成软件包数据。
-.sp
-使用 \fB--no-index\fR,不重新生成搜索索引。
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+不重新生成搜索索引。
+.RE
+
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBrefresh [\fB-p\fR \fIpublisher\fR ...] \fB- s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR\fR
+\fB\fBpkgrepo refresh\fR [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB- -no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
 将在系统信息库中找到的所有新软件包编入目录并更新所有搜索索引。这主要供延迟的发布使用(\fBpkgsend\fR 的 \fB--no-catalog \fR 或 \fB--no-index\fR 选项)。
 .sp
-使用 \fB-p\fR,仅对给定发布者执行操作。如果没有提供该选项或者指定了特定值 \fBall\fR,则对所有发布者执行操作。可以多次指定此选项。
-.sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
-.sp
-使用 \fB--no-catalog\fR,不添加任何新的软件包。
-.sp
-使用 \fB--no-index\fR,不更新搜索索引。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅针对给定发布者执行操作。如果没有提供该选项或者指定了特定值 \fBall\fR,则对所有发布者执行操作。可以多次指定此选项。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBremove [\fB-n\fR] [\fB-p\fR \fI publisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR \fI pkg_fmri_pattern\fR ...\fR\fR
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
+.ad
+.sp .6
+.RS 4n
+不添加任何新软件包。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+不更新搜索索引。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo remove\fR [\fB-n\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fI repo_uri_or_path\fR \fIpkg_fmri_pattern\fR ...\fR
 .ad
 .sp .6
 .RS 4n
@@ -265,18 +480,50 @@
 .RS 2
 此操作不可逆并且不得在其他客户机正在访问系统信息库时使用,因为这样会使得它们在执行检索操作期间出现故障。
 .RE
-使用 \fB-n\fR,执行试运行而不更改软件包。在退出之前,会显示要删除的软件包的列表。
 .sp
-使用 \fB-p\fR,仅删除给定发布者的匹配软件包。如果没有提供该选项,会删除所有发布者的所有匹配软件包。可以多次指定此选项。
-.sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+试运行操作而不进行软件包更改。在退出之前,会显示要删除的软件包的列表。
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBset [\fB-p\fR \fIpublisher\fR] \fB- s\fR \fIrepo_uri_or_path\fR \fIsection/property \fR=[\fIvalue\fR] ... or \fIsection/property \fR=([\fIvalue\fR]) ...\fR\fR
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅删除给定发布者的匹配软件包。如果没有提供该选项,会删除所有发布者的所有匹配软件包。可以多次指定此选项。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo set\fR [\fB-p\fR \fI publisher\fR] \fB-s\fR \fIrepo_uri_or_path\fR \fI section/property\fR=[\fIvalue\fR] ...\fR
+.ad
+.br
+.na
+\fB\fBset\fR [\fB-p\fR \fIpublisher\fR] \fB- s\fR \fIrepo_uri_or_path\fR \fIsection/property \fR=([\fIvalue\fR]) ...\fR
 .ad
 .sp .6
 .RS 4n
@@ -284,10 +531,27 @@
 .sp
 该子命令仅可以与基于文件系统的系统信息库一起使用。
 .sp
-使用 \fB-p\fR,仅设置给定发布者的属性数据。如果发布者尚未存在,将添加该发布者。特殊值 \fB all\fR 可用于设置所有发布者的属性。
+.ne 2
+.mk
+.na
+\fB\fB-p\fR \fIpublisher\fR\fR
+.ad
+.sp .6
+.RS 4n
+仅为给定发布者设置属性数据。如果发布者尚未存在,将添加该发布者。特殊值 \fB all\fR 可用于设置所有发布者的属性。
+.RE
+
 .sp
-使用 \fB-s\fR,对位于给定 URI 或文件系统路径的系统信息库进行操作。
-.sp
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于给定 URI 或文件系统路径的系统信息库进行操作。
+.RE
+
 可以使用以下格式之一指定属性和值:
 .sp
 .ne 2
@@ -327,33 +591,11 @@
 .ne 2
 .mk
 .na
-\fB\fIpublisher\fR/\fIprefix\fR\fR
-.ad
-.sp .6
-.RS 4n
-代表缺省发布者名称的字符串。第一个字符必须是 a-z、A-Z 或 0-9。该字符串的剩余部分只能包含字符 0-9、-、.、a-z 以及 A-Z。该值指明存在多个发布者的软件包时或软件包已发布到系统信息库但未指定发布者时应当使用的发布者。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fIpublisher\fR/\fIsigning_ca_certs \fR\fR
+\fB\fBpublisher/prefix\fR\fR
 .ad
-.sp .6
-.RS 4n
-字符串列表,包含签名 CA 证书(应当用于该发布者)的散列。
-.RE
-
-.sp
-.ne 2
-.mk
-.na
-\fB\fIpublisher\fR/\fIintermediate_certs \fR\fR
-.ad
-.sp .6
-.RS 4n
-字符串列表,包含中间证书(应当用于该发布者)的散列。
+.RS 20n
+.rt  
+代表缺省发布者名称的字符串。第一个字符必须是 a-z、A-Z 或 0-9。该字符串的剩余部分只能包含字符 0-9、-、.、a-z 以及 A-Z。该值指示存在多个发布者的软件包时或者将软件包发布到系统信息库但没有指定发布者时,应当使用的发布者。
 .RE
 
 对于系统信息库第 3 和 4 版,可以为系统信息库中的各发布者设置以下属性:
@@ -361,7 +603,7 @@
 .ne 2
 .mk
 .na
-\fB\fIpublisher\fR/\fIalias\fR\fR
+\fB\fBpublisher/alias\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -372,7 +614,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIcollection_type \fR\fR
+\fB\fBrepository/collection_type\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -387,7 +629,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIdescription \fR\fR
+\fB\fBrepository/description\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -398,7 +640,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIdetailed_url \fR\fR
+\fB\fBrepository/detailed_url\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -409,7 +651,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIlegal_uris \fR\fR
+\fB\fBrepository/legal_uris\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -420,7 +662,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fImirrors\fR\fR
+\fB\fBrepository/mirrors\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -431,7 +673,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIname\fR\fR
+\fB\fBrepository/name\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -442,7 +684,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIorigins\fR\fR
+\fB\fBrepository/origins\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -453,7 +695,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIrefresh_seconds \fR\fR
+\fB\fBrepository/refresh_seconds\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -464,7 +706,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIregistration_uri \fR\fR
+\fB\fBrepository/registration_uri\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -475,7 +717,7 @@
 .ne 2
 .mk
 .na
-\fB\fIrepository\fR/\fIrelated_uris \fR\fR
+\fB\fBrepository/related_uris\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -489,11 +731,22 @@
 .ne 2
 .mk
 .na
-\fB\fBversion\fR\fR
+\fB\fBpkgrepo help\fR\fR
 .ad
 .sp .6
 .RS 4n
-显示标识 \fB pkg\fR(5) 系统版本的唯一字符串。由 \fBversion\fR 操作生成的值不能进行排序,并且对于在不平等情况下的比较而言是不安全的。
+显示用法消息。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo version\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示一个用于唯一标识 \fB pkg\fR(5) 系统版本的字符串。由 \fBversion\fR 操作生成的值不能进行排序,并且对于在不平等情况下的比较而言是不安全的。
 .RE
 
 .SH 示例
@@ -560,12 +813,16 @@
 .sp
 .in +2
 .nf
-$ \fBpkgrepo get -s /my/repository\fR
-SECTION    PROPERTY VALUE
-publisher  prefix   ""
-repository version  4
+$ \fBpkgrepo get -s /export/repoSolaris11\fR
+SECTION    PROPERTY    VALUE
+publisher  prefix      solaris
+repository description Local\e copy\e of\e the\e Oracle\e Solaris\e 11\e repository
+repository name        Oracle\e Solaris\e 11
+repository version     4
 $ \fBpkgrepo get -s http://pkg.oracle.com/solaris/release/\fR
 SECTION    PROPERTY VALUE
+deployment content  s11_11-11
+deployment pubdate  20111102T222051Z
 publisher  prefix   solaris
 repository version  4
 .fi
@@ -582,7 +839,8 @@
 solaris   publisher  alias
 solaris   publisher  prefix           solaris
 solaris   repository collection-type  core
-solaris   repository description      This\e repository\e serves\e the\e Oracle\e Solaris\e 11\e Package\e repository.
+solaris   repository description      This\e repository\e serves\e the\e Oracle\e
+Solaris\e 11\e Package\e repository.
 solaris   repository legal-uris       ()
 solaris   repository mirrors          (http://pkg-cdn1.oracle.com/solaris.release/)
 solaris   repository name             Oracle\e Solaris\e 11\e Package\e Repository
--- a/src/man/zh_CN/pkgsend.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgsend.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,31 +1,31 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgsend 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates.All rights reserved.
+.TH pkgsend 1 "2012 年 6 月 22 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgsend \- 映像包管理系统发布客户机
 .SH 用法概要
 .LP
 .nf
-/usr/bin/pkgsend [\fIoptions\fR] \fIcommand\fR [\fIcmd_options\fR] [\fIoperands\fR]
+/usr/bin/pkgsend [\fIoptions\fR] \fIcommand \fR [\fIcmd_options\fR] [\fIoperands\fR] 
 .fi
 
 .LP
 .nf
-/usr/bin/pkgsend generate [-T \fIpattern\fR] [--target \fIfile\fR]
-    \fIsource\fR ...
+/usr/bin/pkgsend generate [-T \fIpattern\fR] [--target \fI file\fR] \fIsource\fR ...
 .fi
 
 .LP
 .nf
-/usr/bin/pkgsend publish [-b \fIbundle\fR ...] [-d \fIsource\fR ...] 
-    [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog]
-    [\fImanifest\fR ...]
+/usr/bin/pkgsend publish [-b \fIbundle\fR ...] [-d \fI source\fR ...] [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog] [\fImanifest\fR ...]
 .fi
 
 .SH 描述
 .sp
 .LP
 通过 \fBpkgsend\fR,可使用软件包清单将新软件包和新软件包版本发布到映像包管理系统信息库。要创建或管理系统信息库,请参见 \fBpkgrepo\fR(1)。要从现有系统信息库的软件包中创建软件包归档文件,请参见 \fBpkgrecv\fR(1)。有关软件包清单的更多信息,请参见 \fBpkg\fR(5)。
+.sp
+.LP
+完成 \fBpkgsend\fR 操作后,在系统信息库上运行 \fBpkgrepo refresh\fR 或 \fBpkgrepo rebuild\fR 以构建搜索索引。
 .SH 选项
 .sp
 .LP
@@ -34,10 +34,14 @@
 .ne 2
 .mk
 .na
-\fB\fB--help\fR 或 \fB-?\fR\fR
+\fB\fB-?\fR\fR
 .ad
-.RS 17n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 显示用法消息。
 .RE
 
@@ -49,11 +53,16 @@
 .ne 2
 .mk
 .na
-\fB\fBgenerate [\fB-T\fR \fIpattern\fR] [\fB--target\fR \fIfile\fR] \fIsource\fR ... \fR\fR
+\fB\fBpkgsend generate\fR [\fB-T\fR \fI pattern\fR] [\fB--target\fR \fIfile\fR] \fI source\fR ...\fR
 .ad
 .sp .6
 .RS 4n
-读取每个 \fIsource\fR(例如,SVR4 软件包、目录或 \fBtar\fR 文件)并将介绍 \fIsource\fR 的清单发送到 \fBstdout\fR。然后可以注释输出清单,使用 \fBpkgdepend\fR(1) 添加或分析依赖项,并在将其传递到 \fBpublish\fR 子命令之前使用 \fB pkglint\fR(1) 验证它的正确性。以下是支持的源:
+读取每个 \fIsource\fR(例如,SVR4 软件包、目录或 \fBtar\fR 文件)并将介绍 \fIsource\fR 的清单发送到 \fBstdout\fR。在输出清单中,\fBfile\fR 和 \fBdir\fR 操作将所有者设置为 \fBroot\fR,并将组设置为 \fBbin\fR。
+.sp
+然后可以注释输出清单,使用 \fBpkgdepend\fR 添加或分析依赖项,并在将其传递到 \fBpublish\fR 子命令之前使用 \fB pkglint\fR 验证它的正确性。
+.sp
+.LP
+以下是支持的源:
 .RS +4
 .TP
 .ie t \(bu
@@ -83,9 +92,9 @@
 .ne 2
 .mk
 .na
-\fB\fB*\fR\fR
+\fB*\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 匹配所有内容。
 .RE
@@ -94,9 +103,9 @@
 .ne 2
 .mk
 .na
-\fB\fB?\fR\fR
+\fB?\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 匹配任何单个字符。
 .RE
@@ -105,9 +114,9 @@
 .ne 2
 .mk
 .na
-\fB\fB[\fIseq\fR]\fR\fR
+\fB[\fIseq\fR]\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 匹配 \fIseq\fR 中的任何字符。
 .RE
@@ -116,9 +125,9 @@
 .ne 2
 .mk
 .na
-\fB\fB![\fIseq\fR]\fR\fR
+\fB![\fIseq\fR]\fR
 .ad
-.RS 20n
+.RS 10n
 .rt  
 匹配不在 \fIseq\fR 中的任何字符。
 .RE
@@ -134,21 +143,58 @@
 .ne 2
 .mk
 .na
-\fB\fBpublish [\fB-b\fR \fIbundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fI repo_uri_or_path\fR] [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR\fR
+\fB\fBpkgsend publish\fR [\fB-b\fR \fI bundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB-T\fR \fI pattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...] \fR
+.ad
+.sp .6
+.RS 4n
+将使用指定软件包清单的软件包发布到目标软件包系统信息库,并从提供的源中检索该软件包的文件。如果指定了多个清单,它们将以提供的顺序联接。如果未指定清单,则从 \fBstdin\fR 中读取清单。
+.sp
+如果未指定,则 \fBpkgsend publish\fR 向软件包 FMRI 添加内部版本。\fBpublish\fR 工具还向软件包 FMRI 添加时间戳(UTC 中的当前时间)。有关软件包 FMRI 的版本字符串的信息,请参见 \fBpkg \fR(5) 手册页。
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-b\fR \fIbundle\fR\fR
+.ad
+.sp .6
+.RS 4n
+将指定的包添加到源列表,以便在查找清单中的文件时搜索该包。包是 tar 文件和 SVR4 软件包等源。如果多次指定该选项,则以在命令行显示的顺序对源进行搜索。如果同时指定 \fB- b\fR 和 \fB-d\fR,则首先搜索 \fB-d\fR 源。有关支持的包及其使用方法的说明,请参见以上的 \fBgenerate\fR 子命令。
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-d\fR \fIsource\fR\fR
 .ad
 .sp .6
 .RS 4n
-将使用指定软件包清单的软件包发布到目标软件包系统信息库,并从提供的源中检索该软件包的文件。如果指定了多个清单,它们将以提供的顺序联接。如果未指定清单,则从 \fB stdin\fR 中读取清单。
-.sp
-通过 \fB-b\fR,将指定的包添加到源列表,以便在清单中查找文件时进行搜索。包是 tar 文件和 SVR4 软件包等源。如果多次指定该选项,则以在命令行显示的顺序对源进行搜索。如果同时指定 \fB- b\fR 和 \fB-d\fR,则首先搜索 \fB-d\fR 源。有关支持的包及其使用方式的说明,请参阅以上的 \fBgenerate\fR 子命令。
-.sp
-通过 \fB-d\fR,将指定的目录添加到源列表,以便在清单中查找文件时进行搜索。如果多次指定该选项,则以在命令行显示的顺序对源进行搜索。有关支持的源及其使用方式的说明,请参阅以上的 \fBgenerate\fR 子命令。
+将指定的目录添加到源列表,以便在查找清单中的文件时搜索该目录。如果多次指定该选项,则以在命令行显示的顺序对源进行搜索。有关支持的源及其使用方法的说明,请参见以上的 \fBgenerate\fR 子命令。
+.RE
+
 .sp
-通过 \fB-s\fR,将软件包发布到位于给定 URI 或文件系统路径的系统信息库。有关发布限制和建议的更多信息,请参见下面的"附注"部分。另请参见"环境变量"部分。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIrepo_uri_or_path\fR\fR
+.ad
+.sp .6
+.RS 4n
+将软件包发布到位于给定 URI 或文件系统路径的系统信息库。有关发布限制和建议的更多信息,请参见下文的“附注”部分。另请参见“环境变量”部分。
+.RE
+
 .sp
-通过 \fB--no-catalog\fR,不将软件包添加到发布者的目录。当一次发布多个软件包,并且必须连续执行发布者目录更新时,建议使用该选项。完成发布后,可使用 \fBpkgrepo \fR(1) 的 \fBrefresh\fR 子命令将新软件包添加到相应的发布者目录。
-.sp
-有关所有其他选项的用法及其影响,请参阅以上的 \fBgenerate\fR 子命令。
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
+.ad
+.sp .6
+.RS 4n
+不将软件包添加到发布者的目录。当一次发布多个软件包,并且必须连续执行发布者目录更新时,建议使用该选项。完成发布后,可使用 \fBpkgrepo\fR 的 \fBrefresh\fR 子命令将新软件包添加到相应的发布者目录。
+.RE
+
+有关 \fB-T\fR 选项的说明,请参见以上的 \fBgenerate\fR 子命令。
 .RE
 
 .SH 环境变量
--- a/src/man/zh_CN/pkgsign.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pkgsign.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pkgsign 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pkgsign 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pkgsign \- 映像包管理系统签名实用程序
 .SH 用法概要
@@ -23,32 +23,104 @@
 .LP
 支持以下选项:
 .sp
-.LP
-使用 \fB-a\fR,使用签名算法 \fIhash_algorithm \fR 而不是缺省值。缺省签名算法为 \fB rsa-sha256\fR。支持的签名算法包括 \fBrsa-sha256\fR、\fBrsa-sha384\fR、\fBrsa-sha512\fR、\fBsha256\fR、\fBsha384\fR 和 \fBsha512\fR。仅指定散列算法的签名算法会导致签名值为软件包清单的散列。指定 \fBrsa \fR 和散列算法的签名算法会导致签名值为使用提供的私钥签名的清单的散列(请参见 \fB-c\fR 和 \fB- k\fR 选项)。
+.ne 2
+.mk
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
+显示用法消息。
+.RE
+
 .sp
-.LP
-使用 \fB-c\fR,添加证书 \fIpath_to_signing_certificate \fR 以作为验证操作中的签名值时所使用的证书。\fB-c\fR 选项仅可以与 \fB-k\fR 选项一起使用。
+.ne 2
+.mk
+.na
+\fB\fB-a\fR \fIhash_algorithm\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用签名算法 \fIhash_algorithm \fR 而不是缺省值。缺省签名算法为 \fB rsa-sha256\fR。支持的签名算法包括 \fBrsa-sha256\fR、\fBrsa-sha384\fR、\fBrsa-sha512\fR、\fBsha256\fR、\fBsha384\fR 和 \fBsha512\fR。仅指定散列算法的签名算法会导致签名值为软件包清单的散列。指定 \fBrsa \fR 和散列算法的签名算法会导致签名值为使用提供的私钥进行签名的清单的散列(请参见 \fB-c\fR 和 \fB- k\fR 选项)。
+.RE
+
 .sp
-.LP
-使用 \fB-i\fR,添加证书 \fIpath_to_intermediate_cert \fR 以作为验证证书 \fI path_to_signing_certificate\fR(作为参数提供给 \fB-c\fR)时所使用的证书。通过多次指定 \fB-i\fR,可提供多个证书。
+.ne 2
+.mk
+.na
+\fB\fB-c\fR \fIpath_to_signing_certificate\fR\fR
+.ad
+.sp .6
+.RS 4n
+添加证书 \fIpath_to_signing_certificate\fR 作为验证操作中的签名值时所使用的证书。\fB-c\fR 选项仅可以与 \fB-k\fR 选项一起使用。
+.RE
+
 .sp
-.LP
-使用 \fB-k\fR,使用存储在 \fIpath_to_private_key \fR 中的私钥对清单进行签名。\fB-k\fR 选项仅可以与 \fB-c\fR 选项一起使用。如果未设置 \fB-k\fR,则签名值为清单的散列。
+.ne 2
+.mk
+.na
+\fB\fB-i\fR \fIpath_to_intermediate_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+添加证书 \fIpath_to_intermediate_cert\fR 作为验证证书 \fIpath_to_signing_certificate \fR(作为参数提供给 \fB-c\fR)时所使用的证书。通过多次指定 \fB-i\fR,可提供多个证书。
+.RE
+
 .sp
-.LP
-使用 \fB-n\fR,执行试运行,它不会以任何方式更改系统信息库。
+.ne 2
+.mk
+.na
+\fB\fB-k\fR \fIpath_to_private_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+使用存储在 \fIpath_to_private_key \fR 中的私钥对清单进行签名。\fB-k\fR 选项只能与 \fB-c\fR 选项一起使用。如果未设置 \fB-k\fR,则签名值为清单的散列。
+.RE
+
 .sp
-.LP
-使用 \fB-s\fR,对位于 \fIpath_or_uri \fR 的系统信息库中的软件包进行签名。
+.ne 2
+.mk
+.na
+\fB\fB-n\fR\fR
+.ad
+.sp .6
+.RS 4n
+执行试运行,不以任何方式更改系统信息库。
+.RE
+
 .sp
-.LP
-使用 \fB--help\fR,显示用法消息。
+.ne 2
+.mk
+.na
+\fB\fB-s\fR \fIpath_or_uri\fR\fR
+.ad
+.sp .6
+.RS 4n
+对位于 \fIpath_or_uri \fR 的系统信息库中的软件包进行签名。
+.RE
+
 .sp
-.LP
-使用 \fB--no-index\fR,在重新发布已签名的清单后不更新系统信息库搜索索引。
+.ne 2
+.mk
+.na
+\fB\fB--no-index\fR\fR
+.ad
+.sp .6
+.RS 4n
+在重新发布已签名的清单后不更新系统信息库搜索索引。
+.RE
+
 .sp
-.LP
-使用 \fB--no-catalog\fR,在重新发布已签名的清单后不更新系统信息库目录。
+.ne 2
+.mk
+.na
+\fB\fB--no-catalog\fR\fR
+.ad
+.sp .6
+.RS 4n
+在重新发布已签名的清单后不更新系统信息库目录。
+.RE
+
 .SH 示例
 .LP
 \fB示例 1 \fR使用清单的散列值进行签名
@@ -162,7 +234,7 @@
 .SH 另请参见
 .sp
 .LP
-\fBpkg\fR(1)、\fBpkgrecv\fR(1)、\fBpkgsend\fR(1)、\fBpkgrepo\fR(1M)、\fBpkg\fR(5)
+\fBpkg\fR(1)、\fBpkgrecv\fR(1)、\fBpkgsend\fR(1)、\fBpkgrepo\fR(1)、\fBpkg\fR(5)
 .sp
 .LP
 \fBhttp://hub.opensolaris.org/bin/view/Project+pkg/\fR
--- a/src/man/zh_CN/pm-updatemanager.1	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/man/zh_CN/pm-updatemanager.1	Wed Aug 14 11:12:35 2013 +0530
@@ -1,6 +1,6 @@
 '\" te
-.\" Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-.TH pm-updatemanager 1 "2011 年 7 月 28 日" "SunOS 5.11" "用户命令"
+.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.TH pm-updatemanager 1 "2012 年 5 月 27 日" "SunOS 5.11" "用户命令"
 .SH 名称
 pm-updatemanager \- 用于更新软件包的应用程序
 .SH 用法概要
@@ -11,8 +11,8 @@
 
 .LP
 .nf
-/usr/bin/pm-updatemanager [-hdR] [--help] [--debug]
-    [--image-dir \fIdir\fR]
+/usr/bin/pm-updatemanager [-h | --help] [-d | --debug]
+    [-R \fIdir\fR | --image-dir \fIdir\fR]
 .fi
 
 .SH 描述
@@ -33,10 +33,14 @@
 .ne 2
 .mk
 .na
-\fB\fB-h\fR 或 \fB--help\fR\fR
+\fB\fB-h\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--help\fR\fR
+.ad
+.sp .6
+.RS 4n
 显示用法消息。
 .RE
 
@@ -44,10 +48,14 @@
 .ne 2
 .mk
 .na
-\fB\fB-d\fR 或 \fB--debug\fR\fR
+\fB\fB-d\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--debug\fR\fR
+.ad
+.sp .6
+.RS 4n
 在调试模式下运行 \fBpm-updatemanager\fR。
 .RE
 
@@ -55,10 +63,14 @@
 .ne 2
 .mk
 .na
-\fB\fB-R\fR 或 \fB--image-dir\fR\fI dir\fR\fR
+\fB\fB-R\fR \fIdir\fR\fR
 .ad
-.RS 26n
-.rt  
+.br
+.na
+\fB\fB--image-dir\fR \fIdir\fR\fR
+.ad
+.sp .6
+.RS 4n
 对根目录为 \fIdir\fR 的映像(而不是自动搜索到的映像)执行操作。
 .RE
 
@@ -79,7 +91,7 @@
 
 .sp
 .LP
-这是桌面菜单选项"系统">"管理"> "Update Manager" 调用的同一命令。
+这是桌面菜单选项“系统”>“管理”> "Update Manager" 调用的同一命令。
 
 .LP
 \fB示例 2 \fR更新指定映像
--- a/src/modules/actions/depend.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/actions/depend.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 
@@ -32,12 +32,15 @@
 """
 
 import generic
+import re
 
 import pkg.actions
 import pkg.client.pkgdefs as pkgdefs
 import pkg.fmri
 import pkg.version
 
+from pkg.client.firmware import Firmware
+
 known_types = (
     "conditional",
     "exclude",
@@ -178,9 +181,10 @@
                 if required and pkgdefs.PKG_STATE_OBSOLETE in \
                     image.get_pkg_state(installed_version):
                         errors.append(
-                            _("%s dependency on an obsolete package (%s);"
-                            "this package must be uninstalled manually") %
-                            (ctype, installed_version))
+                            _("%(dep_type)s dependency on an obsolete package "
+                            "(%(obs_pkg)s); this package must be uninstalled "
+                            "manually") %
+                            {"dep_type": ctype, "obs_pkg": installed_version})
                         return errors
                 return errors
 
@@ -269,12 +273,20 @@
                                         return [], [], []
                                 else:
                                         errors.extend(e)
-
                         if not errors: # none was installed
                                 errors.append(_("Required dependency on one of "
                                     "%s not met") %
                                     ", ".join((str(p) for p in pfmris)))
                         return errors, warnings, info
+                elif ctype == "origin" and pfmri.pkg_name.startswith(
+                    "feature/firmware/"):
+                        ok, reason = Firmware().check_firmware(self, pfmri.pkg_name)
+                        if ok:
+                                return [], [], []
+                        else:
+                                errors.append(reason)
+
+                        # can only check origin firmware dependencies
 
                 # do checking for other dependency types
 
@@ -307,15 +319,15 @@
                 # it creating a dummy timestamp.  So we have to split it apart
                 # manually.
                 #
-                # XXX This code will need to change if we start using fmris
-                # with publishers in dependencies.
-                #
                 if isinstance(pfmris, basestring):
                         pfmris = [pfmris]
                 inds = []
+                pat = re.compile(r"pkg:///|pkg://[^/]*/|pkg:/") 
                 for p in pfmris:
-                        if p.startswith("pkg:/"):
-                                p = p[5:]
+                        # Strip pkg:/ or pkg:/// from the fmri.
+                        # If fmri has pkg:// then strip the prefix
+                        # from 'pkg://' upto the first slash.
+                        p = pat.sub("", p)
                         # Note that this creates a directory hierarchy!
                         inds.append(
                                 ("depend", ctype, p, None)
--- a/src/modules/actions/directory.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/actions/directory.py	Wed Aug 14 11:12:35 2013 +0530
@@ -156,15 +156,6 @@
                                         # ensure that the mode matches what's
                                         # expected.
                                         os.chmod(path, mode)
-                        # if we're salvaging contents, move 'em now.
-                        # directories with "salvage-from" attribute
-                        # set will scavenge any available contents
-                        # that matches specified directory and
-                        # move it underneath itself on initial install.
-                        # This is here to support directory rename
-                        # when old directory has unpackaged contents
-                        for salvage_from in self.attrlist("salvage-from"):
-                                pkgplan.salvage_from(salvage_from, path)
 
                 # The downside of chmodding the directory is that as a non-root
                 # user, if we set perms u-w, we won't be able to put anything in
@@ -180,6 +171,17 @@
                 elif mode != omode:
                         os.chmod(path, mode)
 
+                # if we're salvaging contents, move 'em now.
+                # directories with "salvage-from" attribute
+                # set will scavenge any available contents
+                # that matches specified directory and
+                # move it underneath itself on install or update.
+                # This is here to support directory rename
+                # when old directory has unpackaged contents, or
+                # consolidation of content from older directories.
+                for salvage_from in self.attrlist("salvage-from"):
+                        pkgplan.salvage_from(salvage_from, path)
+
                 if not orig or oowner != owner or ogroup != group:
                         try:
                                 portable.chown(path, owner, group)
--- a/src/modules/actions/file.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/actions/file.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """module describing a file packaging object
@@ -434,10 +434,8 @@
                 # If the action has been marked with a preserve attribute, and
                 # the file exists and has a content hash different from what the
                 # system expected it to be, then we preserve the original file
-                # in some way, depending on the value of preserve.  If the
-                # action is an overlay, then we always overwrite.
-                overlay = self.attrs.get("overlay") == "true"
-                if is_file and not overlay:
+                # in some way, depending on the value of preserve.
+                if is_file:
                         chash, cdata = misc.get_data_digest(final_path)
                         if not orig or chash != orig.hash:
                                 if pres_type in ("renameold", "renamenew"):
@@ -482,9 +480,17 @@
                     (pkgplan.image.get_root(), self.attrs["path"])))
 
                 # Are we supposed to save this file to restore it elsewhere
-                # or in another pkg?
-                if "save_file" in self.attrs:
+                # or in another pkg? 'save_file' is set by the imageplan.
+                save_file = self.attrs.get("save_file")
+                if save_file:
+                        # 'save_file' contains a tuple of (orig_name,
+                        # remove_file).
+                        remove = save_file[1]
                         self.save_file(pkgplan.image, path)
+                        if remove != "true":
+                                # File must be left in place (this file is
+                                # likely overlaid and is moving).
+                                return
 
                 try:
                         # Make file writable so it can be deleted.
@@ -553,13 +559,13 @@
                         saved_name = None
 
                 ip = image.imageplan
-                ip.saved_files[self.attrs["save_file"]] = (self, saved_name)
+                ip.saved_files[self.attrs["save_file"][0]] = (self, saved_name)
 
         def restore_file(self, image):
                 """restore a previously saved file; return cached action """
 
                 ip = image.imageplan
-                orig, saved_name = ip.saved_files[self.attrs["save_file"]]
+                orig, saved_name = ip.saved_files[self.attrs["save_file"][0]]
                 if saved_name is None:
                         # Nothing to restore; original file is missing.
                         return
--- a/src/modules/actions/generic.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/actions/generic.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """module describing a generic packaging object
@@ -46,6 +46,8 @@
 import pkg.portable as portable
 import pkg.variant as variant
 
+from pkg.misc import EmptyDict
+
 # Directories must precede all filesystem object actions; hardlinks must follow
 # all filesystem object actions (except links).  Note that user and group
 # actions precede file actions (so that the system permits chown'ing them to
@@ -622,6 +624,33 @@
                     (v, self.attrs[v]) for v in self.get_varcet_keys()[0]
                 )))
 
+        def strip(self, preserve=EmptyDict):
+                """Strip actions of attributes which are unnecessary once
+                those actions have been installed in an image.  Stripped
+                actions are saved in an images stripped action cache and used
+                for conflicting actions checks during image planning
+                operations."""
+
+                for key in self.attrs.keys():
+                        # strip out variant and facet information
+                        if key[:8] == "variant." or key[:6] == "facet.":
+                                del self.attrs[key]
+                                continue
+                        # keep unique attributes
+                        if not self.unique_attrs or key in self.unique_attrs:
+                                continue
+                        # keep file action overlay attributes
+                        if self.name == "file" and key == "overlay":
+                                continue
+                        # keep specified keys
+                        if key in preserve.get(self.name, []):
+                                continue
+                        # keep link/hardlink action mediator attributes
+                        if (self.name == "link" or self.name == "hardlink") \
+                            and key[:8] == "mediator":
+                                continue
+                        del self.attrs[key]
+
         def strip_variants(self):
                 """Remove all variant tags from the attrs dictionary."""
 
--- a/src/modules/altroot.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/altroot.py	Wed Aug 14 11:12:35 2013 +0530
@@ -110,8 +110,8 @@
 
         # we're going to update root and path so prepare an error
         # message with the existing values now.
-        eremote = _("Path outside alternate root: root=%s, path=%s") % \
-            (root, path)
+        eremote = _("Path outside alternate root: root=%(root)s, "
+            "path=%(path)s") % {"root": root, "path": path}
 
         # make target into a relative path
         if os.path.isabs(path):
--- a/src/modules/api_common.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/api_common.py	Wed Aug 14 11:12:35 2013 +0530
@@ -133,8 +133,9 @@
         def __init__(self, pfmri, pkg_stem=None, summary=None,
             category_info_list=None, states=None, publisher=None,
             version=None, build_release=None, branch=None, packaging_date=None,
-            size=None, licenses=None, links=None, hardlinks=None, files=None,
-            dirs=None, dependencies=None, description=None, attrs=None):
+            size=None, csize=None, licenses=None, links=None, hardlinks=None,
+            files=None, dirs=None, dependencies=None, description=None,
+            attrs=None):
                 self.pkg_stem = pkg_stem
 
                 self.summary = summary
@@ -148,6 +149,7 @@
                 self.branch = branch
                 self.packaging_date = packaging_date
                 self.size = size
+                self.csize = csize
                 self.fmri = pfmri
                 self.licenses = licenses
                 self.links = links
--- a/src/modules/catalog.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/catalog.py	Wed Aug 14 11:12:35 2013 +0530
@@ -36,6 +36,7 @@
 import stat
 import statvfs
 import threading
+import types
 
 import pkg.actions
 import pkg.client.api_errors as api_errors
@@ -61,7 +62,7 @@
                 self.__single_pass = single_pass
 
                 # Default to a 32K buffer.
-                self.__bufsz = 32 * 1024 
+                self.__bufsz = 32 * 1024
 
                 if sign:
                         if not pathname:
@@ -210,6 +211,9 @@
                 """Initializes a CatalogPartBase object."""
 
                 self.meta_root = meta_root
+                # Sanity check: part names can't be pathname-ish.
+                if name != os.path.basename(name):
+                        raise UnrecognizedCatalogPart(name)
                 self.name = name
                 self.sign = sign
                 self.signatures = {}
@@ -376,6 +380,8 @@
 
                 self.__data = {}
                 self.ordered = ordered
+                if not name.startswith("catalog."):
+                        raise UnrecognizedCatalogPart(name)
                 CatalogPartBase.__init__(self, name, meta_root=meta_root,
                     sign=sign)
 
@@ -915,14 +921,15 @@
                         if cb is None or cb(t, entry):
                                 yield t, entry
 
-        def validate(self, signatures=None):
+        def validate(self, signatures=None, require_signatures=False):
                 """Verifies whether the signatures for the contents of the
                 CatalogPart match the specified signature data, or if not
                 provided, the current signature data.  Raises the exception
                 named 'BadCatalogSignatures' on failure."""
 
-                if not self.signatures and not signatures:
-                        # Nothing to validate.
+                if not self.signatures and not signatures and \
+                    not require_signatures:
+                        # Nothing to validate, and we're not required to.
                         return
 
                 # Ensure content is loaded before attempting to retrieve
@@ -952,6 +959,8 @@
                 """Initializes a CatalogUpdate object."""
 
                 self.__data = {}
+                if not name.startswith("update."):
+                        raise UnrecognizedCatalogPart(name)
                 CatalogPartBase.__init__(self, name, meta_root=meta_root,
                     sign=sign)
 
@@ -1070,14 +1079,15 @@
                                         yield get_update(pub, stem, entry)
                 return
 
-        def validate(self, signatures=None):
+        def validate(self, signatures=None, require_signatures=False):
                 """Verifies whether the signatures for the contents of the
                 CatalogUpdate match the specified signature data, or if not
                 provided, the current signature data.  Raises the exception
                 named 'BadCatalogSignatures' on failure."""
 
-                if not self.signatures and not signatures:
-                        # Nothing to validate.
+                if not self.signatures and not signatures and \
+                    not require_signatures:
+                        # Nothing to validate, and we're not required to.
                         return
 
                 # Ensure content is loaded before attempting to retrieve
@@ -1098,6 +1108,19 @@
         # Properties.
         __data = None
 
+        # This structure defines defaults (for use in __init__) as well as
+        # the set of required elements for this catalog part.  See also the
+        # logic in load().
+        __DEFAULT_ELEMS = {
+            "created": None,
+            "last-modified": None,
+            "package-count": 0,
+            "package-version-count": 0,
+            "parts": {},
+            "updates": {},
+            "version": 1,
+        }
+
         def __init__(self, meta_root=None, sign=True):
                 """Initializes a CatalogAttrs object."""
 
@@ -1110,15 +1133,9 @@
                         # this is actually a new object, so setup some sane
                         # defaults.
                         created = self.__data["last-modified"]
-                        self.__data = {
-                            "created": created,
-                            "last-modified": created,
-                            "package-count": 0,
-                            "package-version-count": 0,
-                            "parts": {},
-                            "updates": {},
-                            "version": 1,
-                        }
+                        self.__data = copy.deepcopy(self.__DEFAULT_ELEMS)
+                        self.__data["created"] = created
+                        self.__data["last-modified"] = created
                 else:
                         # Assume that the attributes of the catalog can be
                         # obtained from a file.
@@ -1200,23 +1217,53 @@
                 if self.loaded:
                         # Already loaded, or only in-memory.
                         return
+                location = os.path.join(self.meta_root, self.name)
 
                 struct = CatalogPartBase.load(self)
+                # Check to see that struct is as we expect: it must be a dict
+                # and have all of the elements in self.__DEFAULT_ELEMS.
+                if type(struct) != types.DictType or \
+                    not (set(self.__DEFAULT_ELEMS.keys()) <= \
+                    set(struct.keys())):
+                        raise api_errors.InvalidCatalogFile(location)
+
+                def cat_ts_to_datetime(val):
+                        try:
+                                return basic_ts_to_datetime(val)
+                        except ValueError:
+                                raise api_errors.InvalidCatalogFile(location)
+
                 for key, val in struct.iteritems():
                         if key in ("created", "last-modified"):
                                 # Convert ISO-8601 basic format strings to
                                 # datetime objects.  These dates can be
                                 # 'null' due to v0 catalog transformations.
                                 if val:
-                                        struct[key] = basic_ts_to_datetime(val)
+                                        struct[key] = cat_ts_to_datetime(val)
                                 continue
 
                         if key in ("parts", "updates"):
+                                if type(val) != types.DictType:
+                                        raise api_errors.InvalidCatalogFile(
+                                            location)
+
+                                # 'parts' and 'updates' have a more complex
+                                # structure.  Check that all of the subparts
+                                # look sane.
+                                for subpart in val:
+                                        if subpart != os.path.basename(subpart):
+                                                raise api_errors.\
+                                                    UnrecognizedCatalogPart(
+                                                    "%s {%s: %s}" % (self.name,
+                                                    key, subpart))
+
+                                # Build datetimes from timestamps.
                                 for e in val:
                                         lm = val[e].get("last-modified", None)
                                         if lm:
-                                                lm = basic_ts_to_datetime(lm)
+                                                lm = cat_ts_to_datetime(lm)
                                                 val[e]["last-modified"] = lm
+
                 self.__data = struct
 
         def save(self):
@@ -1232,14 +1279,15 @@
 
                 CatalogPartBase.save(self, self.__transform(), single_pass=True)
 
-        def validate(self, signatures=None):
+        def validate(self, signatures=None, require_signatures=False):
                 """Verifies whether the signatures for the contents of the
                 CatalogAttrs match the specified signature data, or if not
                 provided, the current signature data.  Raises the exception
                 named 'BadCatalogSignatures' on failure."""
 
-                if not self.signatures and not signatures:
-                        # Nothing to validate.
+                if not self.signatures and not signatures and \
+                    not require_signatures:
+                        # Nothing to validate, and we're not required to.
                         return
 
                 # Ensure content is loaded before attempting to retrieve
@@ -1847,7 +1895,7 @@
                         # current.
 
                         # single-pass encoding is not used for summary part as
-                        # it increases memory usage substantially (30MB at 
+                        # it increases memory usage substantially (30MB at
                         # current for /dev).  No significant difference is
                         # detectable for other parts though.
                         single_pass = name in (self.__BASE_PART,
@@ -3780,12 +3828,12 @@
                 }
                 base.last_modified = op_time
 
-        def validate(self):
+        def validate(self, require_signatures=False):
                 """Verifies whether the signatures for the contents of the
                 catalog match the current signature data.  Raises the
                 exception named 'BadCatalogSignatures' on failure."""
 
-                self._attrs.validate()
+                self._attrs.validate(require_signatures=require_signatures)
 
                 def get_sigs(mdata):
                         sigs = {}
@@ -3805,7 +3853,8 @@
                         if part is None:
                                 # Part does not exist; no validation needed.
                                 continue
-                        part.validate(signatures=get_sigs(mdata))
+                        part.validate(signatures=get_sigs(mdata),
+                            require_signatures=require_signatures)
 
                 for name, mdata in self._attrs.updates.iteritems():
                         ulog = self.__get_update(name, cache=False,
@@ -3813,7 +3862,8 @@
                         if ulog is None:
                                 # Update does not exist; no validation needed.
                                 continue
-                        ulog.validate(signatures=get_sigs(mdata))
+                        ulog.validate(signatures=get_sigs(mdata),
+                            require_signatures=require_signatures)
 
         batch_mode = property(__get_batch_mode, __set_batch_mode)
         last_modified = property(__get_last_modified, __set_last_modified,
@@ -3847,7 +3897,7 @@
         # With the else case above, this should never be None.
         assert catobj
 
-        catobj.validate()
+        catobj.validate(require_signatures=True)
 
 # Methods used by Catalog classes.
 def datetime_to_ts(dt):
@@ -3927,182 +3977,3 @@
         except ValueError:
                 usec = 0
         return datetime.datetime(year, month, day, hour, minutes, sec, usec)
-
-def update_ts_to_datetime(ts):
-        """Take timestamp ts in ISO-8601 basic partial format, and convert it
-        to a datetime object."""
-
-        year = int(ts[0:4])
-        month = int(ts[4:6])
-        day = int(ts[6:8])
-        hour = int(ts[9:11])
-        return datetime.datetime(year, month, day, hour)
-
-def extract_matching_fmris(pkgs, patterns=None, matcher=None,
-    constraint=None, counthash=None, reverse=True, versions=None):
-        """Iterate through the given list of PkgFmri objects,
-        looking for packages matching 'pattern' in 'patterns', based on the
-        function in 'matcher' and the versioning constraint described by
-        'constraint'.  If 'matcher' is None, uses fmri subset matching
-        as the default.  If 'patterns' is None, 'versions' may be specified,
-        and looks for packages matching the patterns specified in 'versions'.
-        When using 'versions', the 'constraint' parameter is ignored.
-
-        'versions' should be a list of strings of the format:
-            release,build_release-branch:datetime
-
-        ...with a value of '*' provided for any component to be ignored. '*' or
-        '?' may be used within each component value and will act as wildcard
-        characters ('*' for one or more characters, '?' for a single character).
-
-        'reverse' is an optional boolean value indicating whether results
-        should be in descending name and version order.  If false, results
-        will be in ascending name, descending version order.
-
-        If 'counthash' is a dictionary, instead store the number of matched
-        fmris for each package that matches."""
-
-        if not matcher:
-                matcher = fmri.fmri_match
-
-        if patterns is None:
-                patterns = []
-        elif not isinstance(patterns, list):
-                patterns = [ patterns ]
-
-        if versions is None:
-                versions = []
-        elif not isinstance(versions, list):
-                versions = [ pkg.version.MatchingVersion(versions, None) ]
-        else:
-                for i, ver in enumerate(versions):
-                        versions[i] = pkg.version.MatchingVersion(ver, None)
-
-        # 'pattern' may be a partially or fully decorated fmri; we want
-        # to extract its name and version to match separately against
-        # the catalog.
-        tuples = {}
-
-        if patterns:
-                matched = {
-                    "matcher": set(),
-                    "publisher": set(),
-                    "version": set(),
-                }
-        elif versions:
-                matched = {
-                    "version": set(),
-                }
-
-        for pattern in patterns:
-                if isinstance(pattern, fmri.PkgFmri):
-                        tuples[pattern] = pattern.tuple()
-                else:
-                        assert pattern != None
-                        # XXX "5.11" here needs to be saner
-                        tuples[pattern] = fmri.PkgFmri(fmri=pattern,
-                            build_release="5.11").tuple()
-
-        def by_pattern(p):
-                cat_pub, cat_name = p.tuple()[:2]
-                pat_match = False
-                for pattern in patterns:
-                        pat_pub, pat_name, pat_version = tuples[pattern]
-
-                        if not pat_pub or fmri.is_same_publisher(pat_pub,
-                            cat_pub):
-                                matched["publisher"].add(pattern)
-                        else:
-                                continue
-
-                        if matcher(cat_name, pat_name):
-                                matched["matcher"].add(pattern)
-                        else:
-                                continue
-
-                        if not pat_version or (p.version.is_successor(
-                            pat_version, constraint) or \
-                            p.version == pat_version):
-                                matched["version"].add(pattern)
-                        else:
-                                continue
-
-                        if counthash is not None:
-                                counthash.setdefault(pattern, 0)
-                                counthash[pattern] += 1
-                        pat_match = True
-
-                if pat_match:
-                        return p
-
-        def by_version(p):
-                pat_match = False
-                for ver in versions:
-                        if p.version == ver:
-                                matched["version"].add(ver)
-                                if counthash is not None:
-                                        sver = str(ver)
-                                        if sver in counthash:
-                                                counthash[sver] += 1
-                                        else:
-                                                counthash[sver] = 1
-                                pat_match = True
-                if pat_match:
-                        return p
-
-        ret = []
-        if patterns:
-                unmatched = copy.deepcopy(matched)
-                for pattern in patterns:
-                        for k in unmatched:
-                                unmatched[k].add(pattern)
-
-                for p in pkgs:
-                        res = by_pattern(p)
-                        if res:
-                                ret.append(res)
-        elif versions:
-                unmatched = copy.deepcopy(matched)
-                for ver in versions:
-                        for k in unmatched:
-                                unmatched[k].add(ver)
-
-                for p in pkgs:
-                        res = by_version(p)
-                        if res:
-                                ret.append(res)
-        else:
-                # No patterns and no versions means that no filtering can be
-                # applied.  It seems silly to call this function in that case,
-                # but the caller will get what it asked for...
-                ret = list(pkgs)
-
-        if patterns or versions:
-                match_types = unmatched.keys()
-                for k in match_types:
-                        # The transformation back to list is important as the
-                        # unmatched results will likely be used to raise an
-                        # InventoryException which expects lists.
-                        unmatched[k] = list(unmatched[k] - matched[k])
-                        if not unmatched[k]:
-                                del unmatched[k]
-                                continue
-                if not unmatched:
-                        unmatched = None
-        else:
-                unmatched = None
-
-        if not reverse:
-                def order(a, b):
-                        res = cmp(a.pkg_name, b.pkg_name)
-                        if res != 0:
-                                return res
-                        res = cmp(a.version, b.version) * -1
-                        if res != 0:
-                                return res
-                        return cmp(a.publisher, b.publisher)
-                ret.sort(cmp=order)
-        else:
-                ret.sort(reverse=True)
-
-        return ret, unmatched
--- a/src/modules/client/__init__.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/__init__.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 # Missing docstring; pylint: disable=C0111
@@ -80,12 +80,15 @@
                 self.client_output_progfd = None
 
                 # concurrency value used for linked image recursion
+                self.client_concurrency_set = False
                 self.client_concurrency_default = 1
                 self.client_concurrency = self.client_concurrency_default
                 try:
                         self.client_concurrency = int(os.environ.get(
                             "PKG_CONCURRENCY",
                             self.client_concurrency_default))
+                        if "PKG_CONCURRENCY" in os.environ:
+                                self.client_concurrency_set = True
                         # remove PKG_CONCURRENCY from the environment so child
                         # processes don't inherit it.
                         os.environ.pop("PKG_CONCURRENCY", None)
--- a/src/modules/client/api.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/api.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """This module provides the supported, documented interface for clients to
@@ -103,8 +103,8 @@
 # things like help(pkg.client.api.PlanDescription)
 from pkg.client.plandesc import PlanDescription # pylint: disable=W0611
 
-CURRENT_API_VERSION = 74
-COMPATIBLE_API_VERSIONS = frozenset([72, 73, CURRENT_API_VERSION])
+CURRENT_API_VERSION = 76
+COMPATIBLE_API_VERSIONS = frozenset([72, 73, 74, 75, CURRENT_API_VERSION])
 CURRENT_P5I_VERSION = 1
 
 # Image type constants.
@@ -253,6 +253,14 @@
         needed.  Cancel may only be invoked while a cancelable method is
         running."""
 
+        FACET_ALL = 0
+        FACET_IMAGE = 1
+        FACET_INSTALLED = 2
+
+        FACET_SRC_SYSTEM = pkg.facet.Facets.FACET_SRC_SYSTEM
+        FACET_SRC_LOCAL = pkg.facet.Facets.FACET_SRC_LOCAL
+        FACET_SRC_PARENT = pkg.facet.Facets.FACET_SRC_PARENT
+
         # Constants used to reference specific values that info can return.
         INFO_FOUND = 0
         INFO_MISSING = 1
@@ -268,6 +276,13 @@
         MATCH_FMRI = 1
         MATCH_GLOB = 2
 
+        VARIANT_ALL = 0
+        VARIANT_ALL_POSSIBLE = 1
+        VARIANT_IMAGE = 2
+        VARIANT_IMAGE_POSSIBLE = 3
+        VARIANT_INSTALLED = 4
+        VARIANT_INSTALLED_POSSIBLE = 5
+
         def __init__(self, img_path, version_id, progresstracker,
             cancel_state_callable, pkg_client_name, exact_match=True,
             cmdpath=None):
@@ -817,6 +832,187 @@
                 dependencies on this) """
                 return [a for a in self._img.get_avoid_dict().iteritems()]
 
+        def gen_facets(self, facet_list, patterns=misc.EmptyI):
+                """A generator function that produces tuples of the form:
+
+                    (
+                        name,    - (string) facet name (e.g. facet.doc)
+                        value    - (boolean) current facet value
+                        src      - (string) source for the value
+                        masked   - (boolean) is the facet maksed by another
+                    )
+
+                Results are always sorted by facet name.
+
+                'facet_list' is one of the following constant values indicating
+                which facets should be returned based on how they were set:
+
+                        FACET_ALL
+                                Return all facets set in the image and all
+                                facets listed in installed packages.
+
+                        FACET_IMAGE
+                                Return only the facets set in the image.
+
+                        FACET_INSTALLED
+                                Return only the facets listed in installed
+                                packages.
+
+                'patterns' is an optional list of facet wildcard strings to
+                filter results by."""
+
+                facets = self._img.cfg.facets
+                if facet_list != self.FACET_INSTALLED:
+                        # Include all facets set in image.
+                        fimg = set(facets.keys())
+                else:
+                        # Don't include any set only in image.
+                        fimg = set()
+
+                # Get all facets found in packages and determine state.
+                fpkg = set()
+                excludes = self._img.list_excludes()
+                if facet_list != self.FACET_IMAGE:
+                        for f in self._img.gen_installed_pkgs():
+                                # The manifest must be loaded without
+                                # pre-applying excludes so that gen_facets() can
+                                # choose how to filter the actions.
+                                mfst = self._img.get_manifest(f,
+                                    ignore_excludes=True)
+                                for facet in mfst.gen_facets(excludes=excludes):
+                                        # Use Facets object to determine
+                                        # effective facet state.
+                                        fpkg.add(facet)
+
+                # Generate the results.
+                for name in misc.yield_matching("facet.", sorted(fimg | fpkg),
+                    patterns):
+                        # check if the facet is explicitly set.
+                        if name not in facets:
+                                # The image's Facets dictionary will return
+                                # the effective value for any facets not
+                                # explicitly set in the image (wildcards or
+                                # implicit). _match_src() will tell us how
+                                # that effective value was determined (via a
+                                # local or inherited wildcard facet, or via a
+                                # system default).
+                                src = facets._match_src(name)
+                                yield (name, facets[name], src, False)
+                                continue
+
+                        # This is an explicitly set facet.
+                        for value, src, masked in facets._src_values(name):
+                                yield (name, value, src, masked)
+
+        def gen_variants(self, variant_list, patterns=misc.EmptyI):
+                """A generator function that produces tuples of the form:
+
+                    (
+                        name,    - (string) variant name (e.g. variant.arch)
+                        value    - (string) current variant value,
+                        possible - (list) list of possible variant values based
+                                   on installed packages; empty unless using
+                                   *_POSSIBLE variant_list.
+                    )
+
+                Results are always sorted by variant name.
+
+                'variant_list' is one of the following constant values indicating
+                which variants should be returned based on how they were set:
+
+                        VARIANT_ALL
+                                Return all variants set in the image and all
+                                variants listed in installed packages.
+
+                        VARIANT_ALL_POSSIBLE
+                                Return possible variant values (those found in
+                                any installed package) for all variants set in
+                                the image and all variants listed in installed
+                                packages.
+
+                        VARIANT_IMAGE
+                                Return only the variants set in the image.
+
+                        VARIANT_IMAGE_POSSIBLE
+                                Return possible variant values (those found in
+                                any installed package) for only the variants set
+                                in the image.
+
+                        VARIANT_INSTALLED
+                                Return only the variants listed in installed
+                                packages.
+
+                        VARIANT_INSTALLED_POSSIBLE
+                                Return possible variant values (those found in
+                                any installed package) for only the variants
+                                listed in installed packages.
+
+                'patterns' is an optional list of variant wildcard strings to
+                filter results by."""
+
+                variants = self._img.cfg.variants
+                if variant_list != self.VARIANT_INSTALLED and \
+                    variant_list != self.VARIANT_INSTALLED_POSSIBLE:
+                        # Include all variants set in image.
+                        vimg = set(variants.keys())
+                else:
+                        # Don't include any set only in image.
+                        vimg = set()
+
+                # Get all variants found in packages and determine state.
+                vpkg = {}
+                excludes = self._img.list_excludes()
+                vposs = collections.defaultdict(set)
+                if variant_list != self.VARIANT_IMAGE:
+                        # Only incur the overhead of reading through all
+                        # installed packages if not just listing variants set in
+                        # image or listing possible values for them.
+                        for f in self._img.gen_installed_pkgs():
+                                # The manifest must be loaded without
+                                # pre-applying excludes so that gen_variants()
+                                # can choose how to filter the actions.
+                                mfst = self._img.get_manifest(f,
+                                    ignore_excludes=True)
+                                for variant, vals in mfst.gen_variants(
+                                    excludes=excludes):
+                                        # Unlike facets, Variants class doesn't
+                                        # handle implicitly set values.
+                                        if variant[:14] == "variant.debug.":
+                                                # Debug variants are implicitly
+                                                # false and are not required
+                                                # to be set explicitly in the
+                                                # image.
+                                                vpkg[variant] = variants.get(
+                                                    variant, "false")
+                                        elif variant not in vimg:
+                                                # Although rare, packages with
+                                                # unknown variants (those not
+                                                # set in the image) can be
+                                                # installed as long as content
+                                                # does not conflict.  For those
+                                                # variants, return None.
+                                                vpkg[variant] = \
+                                                    variants.get(variant)
+
+                                        if (variant_list == \
+                                            self.VARIANT_ALL_POSSIBLE or
+                                            variant_list == \
+                                                self.VARIANT_IMAGE_POSSIBLE or
+                                            variant_list == \
+                                                self.VARIANT_INSTALLED_POSSIBLE):
+                                                # Build possible list of variant
+                                                # values.
+                                                vposs[variant].update(set(vals))
+
+                # Generate the results.
+                for name in misc.yield_matching("variant.",
+                    sorted(vimg | set(vpkg.keys())), patterns):
+                        try:
+                                yield (name, vpkg[name], sorted(vposs[name]))
+                        except KeyError:
+                                yield (name, variants[name],
+                                    sorted(vposs[name]))
+
         def freeze_pkgs(self, fmri_strings, dry_run=False, comment=None,
             unfreeze=False):
                 """Freeze/Unfreeze one or more packages."""
@@ -898,7 +1094,11 @@
                         self.__plan_desc = plan_desc
 
                 self._activity_lock.release()
-                raise
+
+                # re-raise the original exception. (we have to explicitly
+                # restate the original exception since we may have cleared the
+                # current exception scope above.)
+                raise exc_type, exc_value, exc_traceback
 
         def solaris_image(self):
                 """Returns True if the current image is a solaris image, or an
@@ -962,6 +1162,125 @@
 
                 raise apx.IpkgOutOfDateException()
 
+        def __verify_args(self, args):
+                """Verifies arguments passed into the API.
+                It tests for correct data types of the input args, verifies that
+                passed in FMRIs are valid, checks if repository URIs are valid
+                and does some logical tests for the combination of arguments."""
+
+                arg_types = {
+                    # arg name              type                   nullable
+                    "_noexecute":           (bool,                 False),
+                    "_be_activate":         (bool,                 False),
+                    "_new_be":              (bool,                 True),
+                    "_be_name":             (basestring,           True),
+                    "_backup_be":           (bool,                 True),
+                    "_backup_be_name":      (basestring,           True),
+                    "_pubcheck":            (bool,                 False),
+                    "_refresh_catalogs":    (bool,                 False),
+                    "_repos":               (iter,                 True),
+                    "_update_index":        (bool,                 False),
+                    "_li_ignore":           (iter,                 True),
+                    "_li_parent_sync":      (bool,                 False),
+                    "_li_md_only":          (bool,                 False),
+                    "_ipkg_require_latest": (bool,                 False),
+                    "pkgs_inst":            (iter,                 True),
+                    "pkgs_update":          (iter,                 True),
+                    "pkgs_to_uninstall":    (iter,                 True),
+                    "reject_list":          (iter,                 True),
+                    "mediators":            (iter,                 True),
+                    "variants":             (dict,                 True),
+                    "facets":               (pkg.facet.Facets,     True)
+                }
+
+                # merge kwargs into the main arg dict
+                if "kwargs" in args:
+                        for name, value in args["kwargs"].items():
+                                args[name] = value
+
+                # check arguments for proper type and nullability
+                for a in args:
+                        try:
+                                a_type, nullable = arg_types[a]
+                        except KeyError:
+                                # unknown argument passed, ignore
+                                continue
+
+                        assert nullable or args[a] is not None
+
+                        if args[a] is not None and a_type == iter:
+                                try:
+                                        iter(args[a])
+                                except TypeError:
+                                        raise AssertionError("%s is not an "
+                                            "iterable" % a)
+
+                        else:
+                                assert (args[a] is None or
+                                    isinstance(args[a], a_type)), "%s is " \
+                                    "type %s; expected %s" % (a, type(a),
+                                    a_type)
+
+                # check if passed FMRIs are valid
+                illegals = []
+                for i in ("pkgs_inst", "pkgs_update", "pkgs_to_uninstall",
+                    "reject_list"):
+                        try:
+                                fmris = args[i]
+                        except KeyError:
+                                continue
+                        if fmris is None:
+                                continue
+                        for pat, err, pfmri, matcher in \
+                            self.parse_fmri_patterns(fmris):
+                                if not err:
+                                        continue
+                                else:
+                                        illegals.append(fmris)
+
+                if illegals:
+                        raise apx.PlanCreationException(illegal=illegals)
+
+                # some logical checks
+                errors = []
+                if not args["_new_be"] and args["_be_name"]:
+                        errors.append(apx.InvalidOptionError(
+                            apx.InvalidOptionError.REQUIRED, ["_be_name",
+                            "_new_be"]))
+                if not args["_backup_be"] and args["_backup_be_name"]:
+                        errors.append(apx.InvalidOptionError(
+                            apx.InvalidOptionError.REQUIRED, ["_backup_be_name",
+                            "_backup_be"]))
+                if args["_backup_be"] and args["_new_be"]:
+                        errors.append(apx.InvalidOptionError(
+                            apx.InvalidOptionError.INCOMPAT, ["_backup_be",
+                            "_new_be"]))
+
+                if errors:
+                        raise apx.InvalidOptionErrors(errors)
+
+                # check if repo URIs are valid
+                try:
+                        repos = args["_repos"]
+                except KeyError:
+                        return
+
+                if not repos:
+                        return
+
+                illegals = []
+                for r in repos:
+                        valid = False
+                        if type(r) == publisher.RepositoryURI:
+                                # RepoURI objects pass right away
+                                continue
+
+                        if not misc.valid_pub_url(r):
+                                illegals.append(r)
+
+                if illegals:
+                        raise apx.UnsupportedRepositoryURI(illegals)
+
         def __plan_op(self, _op, _ad_kwargs=None,
             _backup_be=None, _backup_be_name=None, _be_activate=True,
             _be_name=None, _ipkg_require_latest=False, _li_ignore=None,
@@ -1008,6 +1327,8 @@
                     _op in [API_OP_ATTACH, API_OP_DETACH, API_OP_SYNC]
                 assert not _li_md_only or _li_parent_sync
 
+                self.__verify_args(locals())
+
                 # make some perf optimizations
                 if _li_md_only:
                         _refresh_catalogs = _update_index = False
@@ -1047,7 +1368,7 @@
 
                         if _li_parent_sync:
                                 # refresh linked image data from parent image.
-                                self._img.linked.syncmd_from_parent(api_op=_op)
+                                self._img.linked.syncmd_from_parent()
 
                         # initialize recursion state
                         self._img.linked.api_recurse_init(
@@ -1557,7 +1878,8 @@
 
         def gen_plan_detach(self, backup_be=None,
             backup_be_name=None, be_activate=True, be_name=None, force=False,
-            li_ignore=None, new_be=False, noexecute=False):
+            li_ignore=None, li_md_only=False, li_pkg_updates=True, new_be=False,
+            noexecute=False):
                 """This is a generator function that yields a PlanDescription
                 object.  If parsable_version is set, it also yields dictionaries
                 containing plan information for child images.
@@ -1582,9 +1904,10 @@
                 return self.__plan_op(op, _ad_kwargs=ad_kwargs,
                     _backup_be=backup_be, _backup_be_name=backup_be_name,
                     _be_activate=be_activate, _be_name=be_name,
-                    _li_ignore=li_ignore, _new_be=new_be,
-                    _noexecute=noexecute, _refresh_catalogs=False,
-                    _update_index=False, li_pkg_updates=False)
+                    _li_ignore=li_ignore, _li_md_only=li_md_only,
+                    _new_be=new_be, _noexecute=noexecute,
+                    _refresh_catalogs=False, _update_index=False,
+                    li_pkg_updates=li_pkg_updates)
 
         def plan_uninstall(self, pkg_list, noexecute=False, update_index=True,
             be_name=None, new_be=False, be_activate=True):
@@ -1597,8 +1920,8 @@
 
         def gen_plan_uninstall(self, pkgs_to_uninstall,
             backup_be=None, backup_be_name=None, be_activate=True,
-            be_name=None, li_ignore=None, new_be=False, noexecute=False,
-            update_index=True):
+            be_name=None, li_ignore=None, li_parent_sync=True, new_be=False,
+            noexecute=False, update_index=True):
                 """This is a generator function that yields a PlanDescription
                 object.  If parsable_version is set, it also yields dictionaries
                 containing plan information for child images.
@@ -1624,7 +1947,7 @@
                 return self.__plan_op(op,
                     _backup_be=backup_be, _backup_be_name=backup_be_name,
                     _be_activate=be_activate, _be_name=be_name,
-                    _li_ignore=li_ignore, _li_parent_sync=False,
+                    _li_ignore=li_ignore, _li_parent_sync=li_parent_sync,
                     _new_be=new_be, _noexecute=noexecute,
                     _refresh_catalogs=False,
                     _update_index=update_index,
@@ -1825,7 +2148,8 @@
                     refresh_catalogs=refresh_catalogs, reject_list=reject_list,
                     show_licenses=show_licenses, update_index=update_index)
 
-        def detach_linked_children(self, li_list, force=False, noexecute=False):
+        def detach_linked_children(self, li_list, force=False,
+            li_md_only=False, li_pkg_updates=True, noexecute=False):
                 """Detach one or more children from the current image. This
                 operation results in the removal of any constraint package
                 from the child images.
@@ -1846,7 +2170,9 @@
                 error."""
 
                 return self._img.linked.detach_children(li_list,
-                    force=force, noexecute=noexecute)
+                    force=force, li_md_only=li_md_only,
+                    li_pkg_updates=li_pkg_updates,
+                    noexecute=noexecute)
 
         def detach_linked_rvdict2rv(self, rvdict):
                 """Convenience function that takes a dictionary returned from
@@ -1913,9 +2239,15 @@
 
                 lin = self._img.linked.child_name
                 rvdict = {}
-                ret = self._img.linked.audit_self(
-                    li_parent_sync=li_parent_sync)
-                rvdict[lin] = ret
+
+                if li_parent_sync:
+                        # refresh linked image data from parent image.
+                        rvdict[lin] = self._img.linked.syncmd_from_parent(
+                            catch_exception=True)
+                        if rvdict[lin] is not None:
+                                return rvdict
+
+                rvdict[lin] = self._img.linked.audit_self()
                 return rvdict
 
         def ischild(self):
@@ -2787,6 +3119,7 @@
                 pkg_pub_map = {}
                 try:
                         progtrack.refresh_start(len(pubs), full_refresh=False)
+                        failed = []
                         pub_cats = []
                         for pub in pubs:
                                 # Assign a temporary meta root to each
@@ -2800,8 +3133,18 @@
 
                                 # Retrieve each publisher's catalog.
                                 progtrack.refresh_start_pub(pub)
-                                pub.refresh()
-                                progtrack.refresh_end_pub(pub)
+                                try:
+                                        pub.refresh()
+                                except apx.PermissionsException, e:
+                                        failed.append((pub, e))
+                                        # No point in continuing since no data
+                                        # can be written.
+                                        break
+                                except apx.ApiException, e:
+                                        failed.append((pub, e))
+                                        continue
+                                finally:
+                                        progtrack.refresh_end_pub(pub)
                                 pub_cats.append((
                                     pub.prefix,
                                     repo,
@@ -2810,6 +3153,12 @@
 
                         progtrack.refresh_done()
 
+                        if failed:
+                                total = len(pub_cats) + len(failed)
+                                e = apx.CatalogRefreshException(failed, total,
+                                    len(pub_cats))
+                                raise e
+
                         # Determine upgradability.
                         newest = {}
                         for pfx, repo, cat in [(None, None, img_inst_cat)] + \
@@ -3004,8 +3353,9 @@
                                 try:
                                         opub = pub_map[pub.prefix]
                                 except KeyError:
+                                        nrepo = publisher.Repository()
                                         opub = publisher.Publisher(pub.prefix,
-                                            catalog=compkcat)
+                                            catalog=compkcat, repository=nrepo)
                                         pub_map[pub.prefix] = opub
 
                         rid_map = {}
@@ -3024,11 +3374,12 @@
                                                            pkg_repos.get(rid).origins
                                                            for rid in rids
                                                         ])
-                                                        nrepo = publisher.Repository(
-                                                            origins=origins)
                                                         npub = \
                                                             copy.copy(pub_map[pub])
-                                                        npub.repository = nrepo
+                                                        nrepo = npub.repository
+                                                        nrepo.origins = origins
+                                                        assert npub.catalog == \
+                                                            compkcat
                                                         rid_map[rids] = npub
 
                                                 pkg_pub_map[pub][stem][ver] = \
@@ -3039,12 +3390,10 @@
                         for pub in pubs:
                                 npub = pub_map[pub.prefix]
                                 nrepo = npub.repository
-                                if not nrepo:
-                                        nrepo = publisher.Repository()
-                                        npub.repository = nrepo
                                 for o in pub.repository.origins:
                                         if not nrepo.has_origin(o):
                                                 nrepo.add_origin(o)
+                                assert npub.catalog == compkcat
 
                         for compcat in (compicat, compkcat):
                                 compcat.batch_mode = False
@@ -3773,7 +4122,7 @@
                                         pub = name = version = None
 
                                 links = hardlinks = files = dirs = \
-                                    size = licenses = cat_info = \
+                                    csize = size = licenses = cat_info = \
                                     description = None
 
                                 if PackageInfo.CATEGORIES in info_needed:
@@ -3824,7 +4173,7 @@
                                                     mfst, alt_pub=alt_pub)
 
                                         if PackageInfo.SIZE in info_needed:
-                                                size = mfst.get_size(
+                                                size, csize = mfst.get_size(
                                                     excludes=excludes)
 
                                         if act_opts & info_needed:
@@ -3845,7 +4194,7 @@
                                                             mfst.gen_key_attribute_value_by_type(
                                                             "dir", excludes))
                                 elif PackageInfo.SIZE in info_needed:
-                                        size = 0
+                                        size = csize = 0
 
                                 # Trim response set.
                                 if PackageInfo.STATE in info_needed:
@@ -3874,7 +4223,7 @@
                                     states=states, publisher=pub, version=release,
                                     build_release=build_release, branch=branch,
                                     packaging_date=packaging_date, size=size,
-                                    pfmri=pfmri, licenses=licenses,
+                                    csize=csize, pfmri=pfmri, licenses=licenses,
                                     links=links, hardlinks=hardlinks, files=files,
                                     dirs=dirs, dependencies=dependencies,
                                     description=description, attrs=attrs))
@@ -4208,16 +4557,20 @@
 
                 slist = []
                 for entry in servers:
-                        descriptive_name = None
                         if isinstance(entry, dict):
                                 origin = entry["origin"]
                                 try:
                                         pub = self._img.get_publisher(
                                             origin=origin)
+                                        pub_uri = publisher.RepositoryURI(
+                                            origin)
+                                        repo = publisher.Repository(
+                                            origins=[pub_uri])
                                 except apx.UnknownPublisher:
                                         pub = publisher.RepositoryURI(origin)
-                                        descriptive_name = origin
-                                slist.append((pub, None, descriptive_name))
+                                        repo = publisher.Repository(
+                                            origins=[pub])
+                                slist.append((pub, repo, origin))
                                 continue
 
                         # Must be a publisher object.
--- a/src/modules/client/api_errors.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/api_errors.py	Wed Aug 14 11:12:35 2013 +0530
@@ -177,7 +177,7 @@
                     "needed": bytes_to_str(self.needed),
                     "use": self.use
                     }
-                    
+
 
 class VersionException(ApiException):
         def __init__(self, expected_version, received_version):
@@ -550,10 +550,11 @@
                         res += [ s % p for p in self.illegal ]
 
                 if self.badarch:
-                        s = _("'%s' supports the following architectures: %s")
+                        s = _("'%(p)s' supports the following architectures: "
+                            "%(archs)s")
                         a = _("Image architecture is defined as: %s")
-                        res += [ s % (self.badarch[0],
-                            ", ".join(self.badarch[1]))]
+                        res += [ s % {"p": self.badarch[0],
+                            "archs": ", ".join(self.badarch[1])}]
                         res += [ a % (self.badarch[2])]
 
                 s = _("'%(p)s' depends on obsolete package '%(op)s'")
@@ -806,8 +807,8 @@
                                 for pkg in sorted(pkglist):
                                         s += _("        %s\n") % pkg
                         else:
-                                t = _("    %d packages deliver '%s', including:\n")
-                                s += t % (num, action)
+                                t = _("    %(n)d packages deliver '%(a)s', including:\n")
+                                s += t % {"n": num, "a": action}
                                 for pkg in sorted(pkglist)[:5]:
                                         s += _("        %s\n") % pkg
 
@@ -1421,7 +1422,7 @@
 
         def __init__(self, v):
                 self.version = v
-        
+
         def __str__(self):
                 return _("%s is not a supported version for creating a "
                     "syspub response.") % self.version
@@ -1453,7 +1454,8 @@
         def __str__(self):
                 if self.location:
                         return _("Error encountered while retrieving data from "
-                            "'%s':\n%s") % (self.location, self.data)
+                            "'%(location)s':\n%(data)s") % \
+                            {"location": self.location, "data": self.data}
                 return _("Error encountered while retrieving data from: %s") % \
                     self.data
 
@@ -1911,16 +1913,40 @@
         """Used to indicate that the specified repository URI uses an
         unsupported scheme."""
 
+        def __init__(self, uris=[]):
+                if isinstance(uris, basestring):
+                        uris = [uris]
+
+                assert isinstance(uris, (list, tuple, set))
+
+                self.uris = uris
+
         def __str__(self):
-                if self.data:
-                        scheme = urlparse.urlsplit(self.data,
+                illegals = []
+
+                for u in self.uris:
+                        assert isinstance(u, basestring)
+                        scheme = urlparse.urlsplit(u,
                             allow_fragments=0)[0]
+                        illegals.append((u, scheme))
+
+                if len(illegals) > 1:
+                        msg = _("The follwing URIs use unsupported "
+                            "schemes.  Supported schemes are "
+                            "file://, http://, and https://.")
+                        for i, s in illegals:
+                                msg += _("\n  %(uri)s (scheme: "
+                                    "%(scheme)s)") % {"uri": i, "scheme": s }
+                        return msg
+                elif len(illegals) == 1:
+                        i, s = illegals[0]
                         return _("The URI '%(uri)s' uses the unsupported "
                             "scheme '%(scheme)s'.  Supported schemes are "
                             "file://, http://, and https://.") % {
-                            "uri": self.data, "scheme": scheme }
+                            "uri": i, "scheme": s }
                 return _("The specified URI uses an unsupported scheme."
-                    "  Supported schemes are: file://, http://, and https://.")
+                    "  Supported schemes are: file://, http://, and "
+                    "https://.")
 
 
 class UnsupportedRepositoryURIAttribute(PublisherError):
@@ -2774,7 +2800,9 @@
                             img_linked
 
                 if lin_malformed is not None:
-                        err = _("Invalid linked image name: '%s'") % \
+                        err = _("Invalid linked image name '%s'. "
+                            "Linked image names have the following format "
+                            "'<linked_image plugin>:<linked_image name>'") % \
                             lin_malformed
 
                 if link_to_self:
@@ -2969,3 +2997,79 @@
                     "found": self.found,
                     "loc": self.loc,
                 }
+
+class InvalidOptionError(ApiException):
+        """Used to indicate an issue with verifying options passed to a certain
+        operation."""
+
+        GENERIC    = "generic"      # generic option violation
+        OPT_REPEAT = "opt_repeat"   # option repetition is not allowed
+        ARG_REPEAT = "arg_repeat"   # argument repetition is not allowed
+        INCOMPAT   = "incompat"     # option 'a' can not be specified with option 'b'
+        REQUIRED   = "required"     # option 'a' requires option 'b'
+        XOR        = "xor"          # either option 'a' or option 'b' must be specified
+
+	def __init__(self, err_type=GENERIC, options=[], msg=None):
+
+                self.err_type = err_type
+                self.options = options
+                self.msg = msg
+
+        def __str__(self):
+
+                # In case the user provided a custom message we just take it and
+                # append the according options.
+                if self.msg is not None:
+                        if self.options:
+                                self.msg += ": "
+                                self.msg += " ".join(self.options)
+                        return self.msg
+
+       		if self.err_type == self.OPT_REPEAT:
+                        assert len(self.options) == 1
+                        return _("Option '%(option)s' may not be repeated.") % {
+                            "option" : self.options[0]}
+                elif self.err_type == self.ARG_REPEAT:
+                        assert len(self.options) == 2
+                        return _("Argument '%(op1)s' for option '%(op2)s' may "
+                            "not be repeated.") % {"op1" : self.options[0],
+                            "op2" : self.options[1]}
+                elif self.err_type == self.INCOMPAT:
+                        assert len(self.options) == 2
+                        return _("The '%(op1)s' and '%(op2)s' option may "
+                            "not be combined.") % {"op1" : self.options[0],
+                            "op2" : self.options[1]}
+                elif self.err_type == self.REQUIRED:
+                        assert len(self.options) == 2
+                        return _("'%(op1)s' may only be used with "
+                            "'%(op2)s'.") % {"op1" : self.options[0],
+                            "op2" : self.options[1]}
+                elif self.err_type == self.XOR:
+                        assert len(self.options) == 2
+                        return _("Either '%(op1)s' or '%(op2)s' must be "
+                            "specified") % {"op1" : self.options[0],
+                            "op2" : self.options[1]}
+                else:
+                        return _("invalid option(s): ") + " ".join(self.options)
+
+class InvalidOptionErrors(ApiException):
+
+        def __init__(self, errors):
+
+                self.errors = []
+
+                assert (isinstance(errors, list) or isinstance(errors, tuple) or
+                    isinstance(errors, set) or
+                    isinstance(errors, InvalidOptionError))
+
+                if isinstance(errors, InvalidOptionError):
+                        self.errors.append(errors)
+                else:
+                        self.errors = errors
+
+        def __str__(self):
+                msgs = []
+                for e in self.errors:
+                        msgs.append(str(e))
+                return "\n".join(msgs)
+
--- a/src/modules/client/bootenv.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/bootenv.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import errno
 import os
@@ -485,7 +485,8 @@
                         # image's history.
                         self.img.history.operation_new_be = self.be_name_clone
                         self.img.history.operation_new_be_uuid = self.be_name_clone_uuid
-                        self.img.history.log_operation_end()
+                        self.img.history.log_operation_end(release_notes=
+			    self.img.imageplan.pd.release_notes_name)
 
                         if be.beUnmount(self.be_name_clone) != 0:
                                 logger.error(_("unable to unmount BE "
@@ -587,9 +588,9 @@
                                 self.img.history.log_operation_error(error=e)
                                 raise e
 
-                        logger.error(_("%s failed to be updated. No changes "
-                            "have been made to %s.") % (self.be_name,
-                            self.be_name))
+                        logger.error(_("%(bename)s failed to be updated. No "
+                            "changes have been made to %(bename)s.") %
+                            {"bename": self.be_name})
 
         def destroy_snapshot(self):
 
@@ -655,10 +656,11 @@
 
                         self.destroy_snapshot()
 
-                        logger.error(_("The Boot Environment %s failed to be "
-                            "updated. A snapshot was taken before the failed "
-                            "attempt and has been restored so no changes have "
-                            "been made to %s.") % (self.be_name, self.be_name))
+                        logger.error(_("The Boot Environment %(bename)s failed "
+                            "to be updated. A snapshot was taken before the "
+                            "failed attempt and has been restored so no "
+                            "changes have been made to %(bename)s.") %
+                            {"bename": self.be_name})
 
         def activate_install_uninstall(self):
                 """Activate an install/uninstall attempt. Which just means
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/client/firmware.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,127 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+import os.path
+import sys
+
+import pkg.misc as misc
+import pkg.pkgsubprocess as subprocess
+import pkg.portable as portable
+
+from pkg.client.debugvalues import DebugValues
+from pkg.actions.generic import quote_attr_value
+
+
+class Firmware(object):
+        def __init__(self):
+            self.__firmware = {} # cache of things we've checked already
+
+        def check_firmware(self, dep_action, firmware_name):
+                """Check firmware dependency.
+                returns ((true, false, none (internal error)),
+                error text)"""
+
+                firmware_dir = "/usr/lib/fwenum"
+                # leverage smf test infrastructure
+                cmds_dir = DebugValues["smf_cmds_dir"]
+                if DebugValues["firmware-dependency-bypass"]:
+                        return (True, None)
+                if cmds_dir: # we're testing;
+                        firmware_dir = cmds_dir
+
+                args = [os.path.join(firmware_dir, firmware_name[len("feature/firmware/"):])]
+                args.extend([
+                    "%s=%s" % (k, quote_attr_value(v))
+                    for k,v in sorted(dep_action.attrs.iteritems())
+                    if k not in ["type", "root-image", "fmri"]
+                ])
+
+                key = str(args)
+
+                # use a cache since each check may be expensive and each
+                # pkg version may have the same dependency.
+                # ignore non-solaris systems here
+
+                if portable.osname != "sunos" and key not in self.firmware:
+                    self.__firmware[key] = (True, None)
+
+                if key not in self.__firmware:
+                        try:
+                                proc = subprocess.Popen(args, stdout=subprocess.PIPE,
+                                    stderr=subprocess.STDOUT)
+                                buf = proc.stdout.readlines()
+                                ret = proc.wait()
+                                # if there was output, something went wrong.
+                                # Since generic errors are often exit(1),
+                                # map this to an internal error.
+                                if ret == 1 and len(buf) > 0:
+                                        ret = 255
+                                if ret == 0:
+                                        ans = (True, None)
+                                elif 0 < ret <= 239:
+                                        ans = (False, (_("There are {0} instances"
+                                            " of downrev firmware for the '{1}' "
+                                            " devices present on this system. "
+                                            "Update each to version {2} or better."
+                                            ).format(ret, args[1],
+                                            dep_action.attrs.get("minimum-version",
+                                            _("UNSPECIFIED")))))
+                                elif ret == 240:
+                                        ans = (False, (_("There are 240 or more "
+                                            "instances of downrev firmware for the"
+                                            "'{0}' devices present on this system. "
+                                            "Update each to version {1} or better."
+                                            ).format(args[1],
+                                            dep_action.attrs.get("minimum-version",
+                                            _("UNSPECIFIED")))))
+                                elif ret < 0:
+                                        ans = (None,
+                                            (_("Firmware dependency error: {0} "
+                                            " exited due to signal {1}").format(
+                                            " ".join(args), misc.signame(-ret))))
+                                else:
+                                        ans = (None,
+                                            (_("Firmware dependency error: General "
+                                            "internal error {0} running '{1}': '{2}'"
+                                            ).format(str(ret), " ".join(args),
+                                            "\n".join(buf))))
+
+                        except OSError, e:
+                                # we have no enumerator installed.  This can
+                                # occur if this driver is being installed
+                                # for the first time or, more likely, we
+                                # just added enumerators & a firmware dependency
+                                # for the first time.  For now, drive on and
+                                # ignore this to permit the addition of such
+                                # dependencies concurrently with their
+                                # enumerarators.
+                                # ans = (None, (_("Firmware dependency error:"
+                                # " Cannot exec {0}: {1}").format(" ".join(args)
+                                # , str(e))))
+                                ans = (True, 0)
+
+                        self.__firmware[key] = ans
+
+                return self.__firmware[key]
--- a/src/modules/client/image.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/image.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import M2Crypto as m2
@@ -361,8 +361,9 @@
                 """A list of strings decribing errors encountered while parsing
                 trust anchors."""
 
-                return [_("%s is expected to be a certificate but could not be "
-                    "parsed.  The error encountered was:\n\t%s") % (p, e)
+                return [_("%(path)s is expected to be a certificate but could "
+                    "not be parsed.  The error encountered was:\n\t%(err)s") %
+                    {"path": p, "err": e}
                     for p, e in self.__bad_trust_anchors
                 ]
 
@@ -2125,7 +2126,7 @@
 
                 # Before continuing, validate SSL information.
                 try:
-                        self.check_cert_validity()
+                        self.check_cert_validity(pubs=[pub])
                 except apx.ExpiringCertificate, e:
                         logger.error(str(e))
 
@@ -2373,18 +2374,18 @@
 
                 return True
 
-        def __verify_manifest(self, fmri, mfstpath):
+        def __verify_manifest(self, fmri, mfstpath, alt_pub=None):
                 """Verify a manifest.  The caller must supply the FMRI
                 for the package in 'fmri', as well as the path to the
                 manifest file that will be verified."""
 
                 try:
                         return self.transport._verify_manifest(fmri,
-                            mfstpath=mfstpath)
+                            mfstpath=mfstpath, pub=alt_pub)
                 except InvalidContentException:
                         return False
         
-        def has_manifest(self, pfmri):
+        def has_manifest(self, pfmri, alt_pub=None):
                 """Check to see if the manifest for pfmri is present on disk and
                 has the correct hash."""
 
@@ -2392,9 +2393,8 @@
                 on_disk = os.path.exists(pth)
 
                 if not on_disk or \
-                    DebugValues.get_value("skip-verify-manifest") or \
                     self.is_pkg_installed(pfmri) or \
-                    self.__verify_manifest(fmri=pfmri, mfstpath=pth):
+                    self.__verify_manifest(fmri=pfmri, mfstpath=pth, alt_pub=alt_pub):
                         return on_disk
                 return False
 
@@ -2457,7 +2457,7 @@
                 object.... grab from server if needed"""
 
                 try:
-                        if not self.has_manifest(fmri):
+                        if not self.has_manifest(fmri, alt_pub=alt_pub):
                                 raise KeyError
                         ret = manifest.FactoredManifest(fmri,
                             self.get_manifest_dir(fmri),
@@ -3027,7 +3027,8 @@
                 # by usage of the SAT solver.
                 newest = {}
                 for pfx, cat in [(None, old_icat)] + pub_cats:
-                        for f in cat.fmris(last=True, pubs=[pfx]):
+                        for f in cat.fmris(last=True,
+                            pubs=pfx and [pfx] or EmptyI):
                                 nver, snver = newest.get(f.pkg_name, (None,
                                     None))
                                 if f.version > nver:
@@ -3294,13 +3295,6 @@
                 self.history.log_operation_start("refresh-publishers",
                     be_name=be_name, be_uuid=be_uuid)
 
-                # Verify validity of certificates before attempting network
-                # operations.
-                try:
-                        self.check_cert_validity()
-                except apx.ExpiringCertificate, e:
-                        logger.error(str(e))
-
                 pubs_to_refresh = []
 
                 if not pubs:
@@ -3326,6 +3320,13 @@
                             result=history.RESULT_NOTHING_TO_DO)
                         return
 
+                # Verify validity of certificates before attempting network
+                # operations.
+                try:
+                        self.check_cert_validity(pubs=pubs_to_refresh)
+                except apx.ExpiringCertificate, e:
+                        logger.error(str(e))
+
                 try:
                         # Ensure Image directory structure is valid.
                         self.mkdirs()
@@ -3552,17 +3553,7 @@
                         for act in m.gen_actions(excludes):
                                 if not act.globally_identical:
                                         continue
-                                for key in act.attrs.keys():
-                                        if (act.unique_attrs and
-                                            key not in act.unique_attrs and
-                                            not (act.name == "file" and
-                                                key == "overlay") and
-                                            not ((act.name == "link" or
-                                                  act.name == "hardlink") and
-                                                 key.startswith("mediator"))) or \
-                                            key.startswith("variant.") or \
-                                            key.startswith("facet."):
-                                                del act.attrs[key]
+                                act.strip()
                                 heappush(heap, (act.name,
                                     act.attrs[act.key_attr], pfmri, act))
                                 nsd.setdefault(act.namespace_group, {})
--- a/src/modules/client/imageconfig.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/imageconfig.py	Wed Aug 14 11:12:35 2013 +0530
@@ -183,6 +183,9 @@
                 cfg.PropertySection("facet", properties=[
                     cfg.PropertyTemplate("^facet\..*", prop_type=cfg.PropBool),
                 ]),
+                cfg.PropertySection("inherited_facet", properties=[
+                    cfg.PropertyTemplate("^facet\..*", prop_type=cfg.PropBool),
+                ]),
                 cfg.PropertySection("mediators", properties=[
                     cfg.PropertyTemplate("^[A-Za-z0-9\-]+\.implementation$"),
                     cfg.PropertyTemplate("^[A-Za-z0-9\-]+\.implementation-version$",
@@ -400,6 +403,9 @@
                 for k, v in idx.get("facet", {}).iteritems():
                         # convert facet name from unicode to a string
                         self.facets[str(urllib.unquote(k))] = v
+                for k, v in idx.get("inherited_facet", {}).iteritems():
+                        # convert facet name from unicode to a string
+                        self.facets._set_inherited(str(urllib.unquote(k)), v)
 
                 # Ensure architecture and zone variants are defined.
                 if "variant.arch" not in self.variants:
@@ -537,9 +543,19 @@
                         self.remove_section("facet")
                 except cfg.UnknownSectionError:
                         pass
-                for f in self.facets:
-                        self.set_property("facet", urllib.quote(f, ""), 
-                            self.facets[f])
+                # save local facets
+                for f in self.facets.local:
+                        self.set_property("facet",
+                            urllib.quote(f, ""), self.facets.local[f])
+
+                try:
+                        self.remove_section("inherited_facet")
+                except cfg.UnknownSectionError:
+                        pass
+                # save inherited facets
+                for f in self.facets.inherited:
+                        self.set_property("inherited_facet",
+                            urllib.quote(f, ""), self.facets.inherited[f])
 
                 try:
                         self.remove_section("mediators")
--- a/src/modules/client/imageplan.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/imageplan.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,17 +21,18 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 from collections import defaultdict, namedtuple
 import contextlib
 import errno
+import fnmatch
 import itertools
 import mmap
 import operator
 import os
-import simplejson as json
+import stat
 import sys
 import tempfile
 import traceback
@@ -43,7 +44,6 @@
 import pkg.actions
 import pkg.actions.driver as driver
 import pkg.catalog
-import pkg.client.actuator as actuator
 import pkg.client.api_errors as api_errors
 import pkg.client.indexer as indexer
 import pkg.client.pkg_solver as pkg_solver
@@ -232,7 +232,8 @@
                 return self.pd._cbytes_avail
 
         def __vector_2_fmri_changes(self, installed_dict, vector,
-            li_pkg_updates=True, new_variants=None, new_facets=None):
+            li_pkg_updates=True, new_variants=None, new_facets=None,
+            fmri_changes=None):
                 """Given an installed set of packages, and a proposed vector
                 of package changes determine what, if any, changes should be
                 made to the image.  This takes into account different
@@ -240,43 +241,30 @@
                 where the only packages being updated are linked image
                 constraints, etc."""
 
-                cat = self.image.get_catalog(self.image.IMG_CATALOG_KNOWN)
-
                 fmri_updates = []
+                if fmri_changes is not None:
+                        affected = [f[0] for f in fmri_changes]
+                else:
+                        affected = None
+
                 for a, b in ImagePlan.__dicts2fmrichanges(installed_dict,
                     ImagePlan.__fmris2dict(vector)):
                         if a != b:
                                 fmri_updates.append((a, b))
                                 continue
-                        if new_facets is not None or new_variants:
-                                #
-                                # In the case of a facet change we reinstall
-                                # packages since any action in a package could
-                                # have a facet attached to it.
-                                #
-                                # In the case of variants packages should
-                                # declare what variants they contain.  Hence,
-                                # theoretically, we should be able to reduce
-                                # the number of package reinstalls by removing
-                                # re-installs of packages that don't declare
-                                # variants.  But unfortunately we've never
-                                # enforced this requirement that packages with
-                                # action variant tags declare their variants.
-                                # So now we're stuck just re-installing every
-                                # package.  sigh.
-                                #
-                                fmri_updates.append((a, b))
-                                continue
-
-                if not fmri_updates:
-                        # no planned fmri changes
-                        return []
-
-                if fmri_updates and not li_pkg_updates:
-                        # oops.  the caller requested no package updates and
-                        # we couldn't satisfy that request.
-                        raise api_errors.PlanCreationException(
-                            pkg_updates_required=fmri_updates)
+
+                        if (new_facets is not None or new_variants):
+                                if affected is None or a in affected:
+                                        # If affected list of packages has not
+                                        # been predetermined for package fmris
+                                        # that are unchanged, or if the fmri
+                                        # exists in the list of affected
+                                        # packages, add it to the list.
+                                        fmri_updates.append((a, a))
+
+                # cache li_pkg_updates in the plan description for later
+                # evaluation
+                self.pd._li_pkg_updates = li_pkg_updates
 
                 return fmri_updates
 
@@ -286,37 +274,129 @@
 
                 self.pd._image_lm = self.image.get_last_modified(string=True)
 
+        def __merge_inherited_facets(self, new_facets=None):
+                """Merge any new facets settings with (possibly changing)
+                inherited facets."""
+
+                if new_facets is not None:
+                        # make sure we don't accidentally update the caller
+                        # supplied facets.
+                        new_facets = pkg.facet.Facets(new_facets)
+
+                        # we don't allow callers to specify inherited facets
+                        # (they can only come from parent images.)
+                        new_facets._clear_inherited()
+
+                # get the existing image facets.
+                old_facets = self.image.cfg.facets
+
+                if new_facets is None:
+                        # the user did not request any facet changes, but we
+                        # still need to see if inherited facets are changing.
+                        # so set new_facets to the existing facet set with
+                        # inherited facets removed.
+                        new_facets = pkg.facet.Facets(old_facets)
+                        new_facets._clear_inherited()
+
+                # get the latest inherited facets and merge them into the user
+                # specified facets.
+                new_facets.update(self.image.linked.inherited_facets())
+
+                if new_facets == old_facets:
+                        # there are no caller specified or inherited facet
+                        # changes.
+                        return (None, False, False)
+
+                facet_change = bool(old_facets._cmp_values(new_facets)) or \
+                    bool(old_facets._cmp_priority(new_facets))
+                masked_facet_change = bool(not facet_change) and \
+                    bool(old_facets._cmp_all_values(new_facets))
+
+                # Something better be changing.  But if visible facets are
+                # changing we don't report masked facet changes.
+                assert facet_change != masked_facet_change
+
+                return (new_facets, facet_change, masked_facet_change)
+
+        def __evaluate_varcets(self, new_variants=None, new_facets=None):
+                """Private helper function used to determine new facet and
+                variant state for image."""
+
+                # merge caller supplied and inherited facets
+                new_facets, facet_change, masked_facet_change = \
+                    self.__merge_inherited_facets(new_facets)
+
+                # if we're changing variants or facets, save that to the plan.
+                if new_variants or facet_change or masked_facet_change:
+                        self.pd._varcets_change = True
+                        self.pd._new_variants = new_variants
+                        self.pd._old_facets   = self.image.cfg.facets
+                        self.pd._new_facets   = new_facets
+                        self.pd._facet_change = facet_change
+                        self.pd._masked_facet_change = masked_facet_change
+
+                self.__new_excludes = self.image.list_excludes(new_variants,
+                    new_facets)
+
+                return (new_variants, new_facets, facet_change,
+                    masked_facet_change)
+
+        def __run_solver(self, solver_cb, retry_wo_parent_deps=True):
+                """Run the solver, and if it fails, optionally retry the
+                operation once while relaxing installed parent
+                dependencies."""
+
+                # have the solver try to satisfy parent dependencies.
+                ignore_inst_parent_deps = False
+
+                try:
+                        return solver_cb(ignore_inst_parent_deps)
+                except api_errors.PlanCreationException, e:
+                        # if we're currently in sync don't retry the
+                        # operation
+                        if self.image.linked.insync(latest_md=False):
+                                raise e
+                        # if PKG_REQUIRE_SYNC is set in the
+                        # environment we require an in-sync image.
+                        if "PKG_REQUIRE_SYNC" in os.environ:
+                                raise e
+                        # caller doesn't want us to retry
+                        if not retry_wo_parent_deps:
+                                raise e
+                        # we're an out-of-sync child image so retry
+                        # this operation while ignoring parent
+                        # dependencies for any installed packages.  we
+                        # do this so that users can manipulate out of
+                        # sync images in an attempt to bring them back
+                        # in sync.  since we don't ignore parent
+                        # dependencies for uninstalled packages, the
+                        # user won't be able to take the image further
+                        # out of sync.
+                        ignore_inst_parent_deps = True
+                        return solver_cb(ignore_inst_parent_deps)
+
         def __plan_install_solver(self, li_pkg_updates=True, li_sync_op=False,
             new_facets=None, new_variants=None, pkgs_inst=None,
-            reject_list=misc.EmptyI):
+            reject_list=misc.EmptyI, fmri_changes=None):
                 """Use the solver to determine the fmri changes needed to
                 install the specified pkgs, sync the specified image, and/or
                 change facets/variants within the current image."""
 
-                if not (new_variants or pkgs_inst or li_sync_op or
-                    new_facets is not None):
-                        # nothing to do
+                # evaluate what varcet changes are required
+                new_variants, new_facets, \
+                    facet_change, masked_facet_change = \
+                    self.__evaluate_varcets(new_variants, new_facets)
+
+                # check if we need to uninstall any packages.
+                uninstall = self.__any_reject_matches(reject_list)
+
+                # check if anything is actually changing.
+                if not (li_sync_op or pkgs_inst or uninstall or
+                    new_variants or facet_change or fmri_changes is not None):
+                        # the solver is not necessary.
                         self.pd._fmri_changes = []
                         return
 
-                old_facets = self.image.cfg.facets
-                if new_variants or \
-                    (new_facets is not None and new_facets != old_facets):
-                        self.pd._varcets_change = True
-                        self.pd._new_variants = new_variants
-                        self.pd._new_facets   = new_facets
-                        tmp_new_facets = new_facets
-                        if tmp_new_facets is None:
-                                tmp_new_facets = pkg.facet.Facets()
-                        self.pd._changed_facets = pkg.facet.Facets(dict(
-                            set(tmp_new_facets.iteritems()) -
-                            set(old_facets.iteritems())))
-                        self.pd._removed_facets = set(old_facets.keys()) - \
-                            set(tmp_new_facets.keys())
-
-                if new_facets == old_facets:
-                        new_facets = None
-
                 # get ranking of publishers
                 pub_ranks = self.image.get_publisher_ranks()
 
@@ -339,40 +419,51 @@
                 else:
                         inst_dict = {}
 
-                self.__new_excludes = self.image.list_excludes(new_variants,
-                    new_facets)
-
                 if new_variants:
                         variants = new_variants
                 else:
                         variants = self.image.get_variants()
 
-                # instantiate solver
-                solver = pkg_solver.PkgSolver(
-                    self.image.get_catalog(self.image.IMG_CATALOG_KNOWN),
-                    installed_dict,
-                    pub_ranks,
-                    variants,
-                    self.image.avoid_set_get(),
-                    self.image.linked.parent_fmris(),
-                    self.__progtrack)
-
-                # If this isn't a sync-linked operation then set
-                # ignore_inst_parent_deps to True to allow us to modify
-                # out of sync images.
-                ignore_inst_parent_deps = not li_sync_op
-
-                # Solve... will raise exceptions if no solution is found
-                new_vector, self.pd._new_avoid_obs = solver.solve_install(
-                        self.image.get_frozen_list(), inst_dict,
-                        new_variants=new_variants, excludes=self.__new_excludes,
-                        reject_set=reject_set, relax_all=li_sync_op,
-                        ignore_inst_parent_deps=ignore_inst_parent_deps)
+                def solver_cb(ignore_inst_parent_deps):
+                        # instantiate solver
+                        solver = pkg_solver.PkgSolver(
+                            self.image.get_catalog(
+                                self.image.IMG_CATALOG_KNOWN),
+                            installed_dict,
+                            pub_ranks,
+                            variants,
+                            self.image.avoid_set_get(),
+                            self.image.linked.parent_fmris(),
+                            self.__progtrack)
+
+                        # run solver
+                        new_vector, new_avoid_obs = \
+                            solver.solve_install(
+                                self.image.get_frozen_list(),
+                                inst_dict,
+                                new_variants=new_variants,
+                                excludes=self.__new_excludes,
+                                reject_set=reject_set,
+                                relax_all=li_sync_op,
+                                ignore_inst_parent_deps=\
+                                    ignore_inst_parent_deps)
+
+                        return solver, new_vector, new_avoid_obs
+
+                # We can't retry this operation while ignoring parent
+                # dependencies if we're doing a linked image sync.
+                retry_wo_parent_deps = not li_sync_op
+
+                # Solve; will raise exceptions if no solution is found.
+                solver, new_vector, self.pd._new_avoid_obs = \
+                    self.__run_solver(solver_cb, \
+                        retry_wo_parent_deps=retry_wo_parent_deps)
 
                 self.pd._fmri_changes = self.__vector_2_fmri_changes(
                     installed_dict, new_vector,
                     li_pkg_updates=li_pkg_updates,
-                    new_variants=new_variants, new_facets=new_facets)
+                    new_variants=new_variants, new_facets=new_facets,
+                    fmri_changes=fmri_changes)
 
                 self.pd._solver_summary = str(solver)
                 if DebugValues["plan"]:
@@ -418,13 +509,190 @@
                 self.__plan_install(pkgs_inst=pkgs_inst,
                      reject_list=reject_list)
 
+        def __get_attr_fmri_changes(self, get_mattrs):
+                # Attempt to optimize package planning by determining which
+                # packages are actually affected by changing attributes (e.g.,
+                # facets, variants).  This also provides an accurate list of
+                # affected packages as a side effect (normally, all installed
+                # packages are seen as changed).  This assumes that facets and
+                # variants are not both changing at the same time.
+                use_solver = False
+                cat = self.image.get_catalog(
+                    self.image.IMG_CATALOG_INSTALLED)
+                cat_info = frozenset([cat.DEPENDENCY])
+
+                fmri_changes = []
+                pt = self.__progtrack
+                rem_pkgs = self.image.count_installed_pkgs()
+
+                pt.plan_start(pt.PLAN_PKGPLAN, goal=rem_pkgs)
+                for f in self.image.gen_installed_pkgs():
+                        m = self.image.get_manifest(f,
+                            ignore_excludes=True)
+
+                        # Get the list of attributes involved in this operation
+                        # that the package uses and that have changed.
+                        use_solver, mattrs = get_mattrs(m, use_solver)
+                        if not mattrs:
+                                # Changed attributes unused.
+                                pt.plan_add_progress(pt.PLAN_PKGPLAN)
+                                rem_pkgs -= 1
+                                continue
+
+                        # Changed attributes are used in this package.
+                        fmri_changes.append((f, f))
+
+                        # If any dependency actions are tagged with one
+                        # of the changed attributes, assume the solver
+                        # must be used.
+                        for act in cat.get_entry_actions(f, cat_info):
+                                for attr in mattrs:
+                                        if use_solver:
+                                                break
+                                        if (act.name == "depend" and
+                                            attr in act.attrs):
+                                                use_solver = True
+                                                break
+                                if use_solver:
+                                        break
+
+                        rem_pkgs -= 1
+                        pt.plan_add_progress(pt.PLAN_PKGPLAN)
+
+                pt.plan_done(pt.PLAN_PKGPLAN)
+                pt.plan_all_done()
+
+                return use_solver, fmri_changes
+
+        def __facet_change_fastpath(self):
+                """The following optimizations only work correctly if only
+                facets are changing (not variants, uninstalls, etc)."""
+
+                old_facets = self.pd._old_facets
+                new_facets = self.pd._new_facets
+
+                changed_facets = [
+                        f
+                        for f in new_facets
+                        if f not in old_facets or \
+                            old_facets[f] != new_facets[f]
+                ]
+
+                def get_fattrs(m, use_solver):
+                        # Get the list of facets involved in this
+                        # operation that the package uses.  To
+                        # accurately determine which packages are
+                        # actually being changed, we must compare the
+                        # old effective value for each facet that is
+                        # changing with its new effective value.
+                        return use_solver, list(
+                            f
+                            for f in m.gen_facets(
+                                excludes=self.__new_excludes,
+                                patterns=changed_facets)
+                            if new_facets[f] != old_facets[f]
+                        )
+
+                return self.__get_attr_fmri_changes(get_fattrs)
+
+        def __variant_change_fastpath(self):
+                """The following optimizations only work correctly if only
+                variants are changing (not facets, uninstalls, etc)."""
+
+                nvariants = self.pd._new_variants
+
+                def get_vattrs(m, use_solver):
+                        # Get the list of variants involved in this
+                        # operation that the package uses.
+                        mvars = []
+                        for (variant, pvals) in m.gen_variants(
+                            excludes=self.__new_excludes,
+                            patterns=nvariants
+                        ):
+                                if nvariants[variant] not in pvals:
+                                        # If the new value for the
+                                        # variant is unsupported by this
+                                        # package, then the solver
+                                        # should be triggered so the
+                                        # package can be removed.
+                                        use_solver = True
+                                mvars.append(variant)
+                        return use_solver, mvars
+
+                return self.__get_attr_fmri_changes(get_vattrs)
+
         def plan_change_varcets(self, new_facets=None, new_variants=None,
             reject_list=misc.EmptyI):
                 """Determine the fmri changes needed to change the specified
                 facets/variants."""
 
-                self.__plan_install(new_facets=new_facets,
-                     new_variants=new_variants, reject_list=reject_list)
+                self.__plan_op()
+
+                # assume none of our optimizations will work.
+                fmri_changes = None
+
+                # convenience function to invoke the solver.
+                def plan_install_solver():
+                        self.__plan_install_solver(
+                            new_facets=new_facets,
+                            new_variants=new_variants,
+                            reject_list=reject_list,
+                            fmri_changes=fmri_changes)
+                        self.pd.state = plandesc.EVALUATED_PKGS
+
+                # evaluate what varcet changes are required
+                new_variants, new_facets, \
+                    facet_change, masked_facet_change = \
+                    self.__evaluate_varcets(new_variants, new_facets)
+
+                # uninstalling packages requires the solver.
+                uninstall = self.__any_reject_matches(reject_list)
+                if uninstall:
+                        plan_install_solver()
+                        return
+
+                # All operations (including varcet changes) need to try and
+                # keep linked images in sync.  Linked image audits are fast,
+                # so do one now and if we're not in sync we need to invoke the
+                # solver.
+                if not self.image.linked.insync():
+                        plan_install_solver()
+                        return
+
+                # if facets and variants are changing at the same time, then
+                # we need to invoke the solver.
+                if new_variants and facet_change:
+                        plan_install_solver()
+                        return
+
+                # By default, we assume the solver must be used.  If any of the
+                # optimizations below can be applied, they'll determine whether
+                # the solver can be used.
+                use_solver = True
+
+                # the following facet optimization only works if we're not
+                # changing variants at the same time.
+                if facet_change:
+                        assert not new_variants
+                        use_solver, fmri_changes = \
+                            self.__facet_change_fastpath()
+
+                # the following variant optimization only works if we're not
+                # changing facets at the same time.
+                if new_variants:
+                        assert not facet_change
+                        use_solver, fmri_changes = \
+                            self.__variant_change_fastpath()
+
+                if use_solver:
+                        plan_install_solver()
+                        return
+
+                # If solver isn't involved, assume the list of packages
+                # has been determined.
+                assert fmri_changes is not None
+                self.pd._fmri_changes = fmri_changes
+                self.pd.state = plandesc.EVALUATED_PKGS
 
         def plan_set_mediators(self, new_mediators):
                 """Determine the changes needed to set the specified mediators.
@@ -564,27 +832,36 @@
                 pt.plan_done(pt.PLAN_MEDIATION_CHG)
                 self.pd.state = plandesc.EVALUATED_PKGS
 
+        def __any_reject_matches(self, reject_list):
+                """Check if any reject patterns match installed packages (in
+                which case a packaging operation should attempt to uninstall
+                those packages)."""
+
+                # return true if any packages in reject list
+                # match any installed packages
+                return bool(reject_list) and \
+                    bool(self.match_user_stems(self.image, reject_list,
+                        self.MATCH_INST_VERSIONS, raise_not_installed=False))
+
         def plan_sync(self, li_pkg_updates=True, reject_list=misc.EmptyI):
                 """Determine the fmri changes needed to sync the image."""
 
-                # check if the sync will try to uninstall packages.
-                uninstall = False
-                reject_set = self.match_user_stems(self.image, reject_list,
-                    self.MATCH_INST_VERSIONS, raise_not_installed=False)
-                if reject_set:
-                        # at least one reject pattern matched an installed
-                        # package
-                        uninstall = True
+                self.__plan_op()
+
+                # check if we need to uninstall any packages.
+                uninstall = self.__any_reject_matches(reject_list)
+
+                # check if inherited facets are changing
+                new_facets = self.__evaluate_varcets()[1]
 
                 # audits are fast, so do an audit to check if we're in sync.
-                rv, err, p_dict = self.image.linked.audit_self(
-                    li_parent_sync=False)
-
-                # if we're not trying to uninstall packages and we're
-                # already in sync then don't bother invoking the solver.
-                if not uninstall and rv == pkgdefs.EXIT_OK:
+                insync = self.image.linked.insync()
+
+                # if we're not trying to uninstall packages, and inherited
+                # facets are not changing, and we're already in sync, then
+                # don't bother invoking the solver.
+                if not uninstall and not new_facets is not None and insync:
                         # we don't need to do anything
-                        self.__plan_op()
                         self.pd._fmri_changes = []
                         self.pd.state = plandesc.EVALUATED_PKGS
                         return
@@ -603,33 +880,43 @@
                     for f in each
                 ])
 
+                # check if inherited facets are changing
+                new_facets = self.__evaluate_varcets()[1]
+
                 # build installed dict
                 installed_dict = ImagePlan.__fmris2dict(
                     self.image.gen_installed_pkgs())
 
-                # instantiate solver
-                solver = pkg_solver.PkgSolver(
-                    self.image.get_catalog(self.image.IMG_CATALOG_KNOWN),
-                    installed_dict,
-                    self.image.get_publisher_ranks(),
-                    self.image.get_variants(),
-                    self.image.avoid_set_get(),
-                    self.image.linked.parent_fmris(),
-                    self.__progtrack)
-
-                # Set ignore_inst_parent_deps to True to allow us to
-                # modify out of sync images.
-                new_vector, self.pd._new_avoid_obs = solver.solve_uninstall(
-                    self.image.get_frozen_list(), proposed_removals,
-                    self.__new_excludes,
-                    ignore_inst_parent_deps=True)
-
-                self.pd._fmri_changes = [
-                    (a, b)
-                    for a, b in ImagePlan.__dicts2fmrichanges(installed_dict,
-                        ImagePlan.__fmris2dict(new_vector))
-                    if a != b
-                ]
+                def solver_cb(ignore_inst_parent_deps):
+                        # instantiate solver
+                        solver = pkg_solver.PkgSolver(
+                            self.image.get_catalog(
+                                self.image.IMG_CATALOG_KNOWN),
+                            installed_dict,
+                            self.image.get_publisher_ranks(),
+                            self.image.get_variants(),
+                            self.image.avoid_set_get(),
+                            self.image.linked.parent_fmris(),
+                            self.__progtrack)
+
+                        # run solver
+                        new_vector, new_avoid_obs = \
+                            solver.solve_uninstall(
+                                self.image.get_frozen_list(),
+                                proposed_removals,
+                                self.__new_excludes,
+                                ignore_inst_parent_deps=\
+                                    ignore_inst_parent_deps)
+
+                        return solver, new_vector, new_avoid_obs
+
+                # Solve; will raise exceptions if no solution is found.
+                solver, new_vector, self.pd._new_avoid_obs = \
+                    self.__run_solver(solver_cb)
+
+                self.pd._fmri_changes = self.__vector_2_fmri_changes(
+                    installed_dict, new_vector,
+                    new_facets=new_facets)
 
                 self.pd._solver_summary = str(solver)
                 if DebugValues["plan"]:
@@ -642,6 +929,10 @@
                 """Use the solver to determine the fmri changes needed to
                 update the specified pkgs or all packages if none were
                 specified."""
+
+                # check if inherited facets are changing
+                new_facets = self.__evaluate_varcets()[1]
+
                 # get ranking of publishers
                 pub_ranks = self.image.get_publisher_ranks()
 
@@ -664,37 +955,52 @@
                             reject_set=reject_set)
                         self.__match_update = references
 
-                # instantiate solver
-                solver = pkg_solver.PkgSolver(
-                    self.image.get_catalog(self.image.IMG_CATALOG_KNOWN),
-                    installed_dict,
-                    pub_ranks,
-                    self.image.get_variants(),
-                    self.image.avoid_set_get(),
-                    self.image.linked.parent_fmris(),
-                    self.__progtrack)
-
-                if pkgs_update:
-                        # Set ignore_inst_parent_deps to True to allow us to
-                        # modify out of sync images.
-                        new_vector, self.pd._new_avoid_obs = \
-                            solver.solve_install(
-                                self.image.get_frozen_list(),
-                                update_dict, excludes=self.__new_excludes,
-                                reject_set=reject_set,
-                                trim_proposed_installed=False,
-                                ignore_inst_parent_deps=True)
-                else:
-                        # Updating all installed packages requires a different
-                        # solution path.
-                        new_vector, self.pd._new_avoid_obs = \
-                            solver.solve_update_all(
-                                self.image.get_frozen_list(),
-                                excludes=self.__new_excludes,
-                                reject_set=reject_set)
+                def solver_cb(ignore_inst_parent_deps):
+                        # instantiate solver
+                        solver = pkg_solver.PkgSolver(
+                            self.image.get_catalog(
+                                self.image.IMG_CATALOG_KNOWN),
+                            installed_dict,
+                            pub_ranks,
+                            self.image.get_variants(),
+                            self.image.avoid_set_get(),
+                            self.image.linked.parent_fmris(),
+                            self.__progtrack)
+
+                        # run solver
+                        if pkgs_update:
+                                new_vector, new_avoid_obs = \
+                                    solver.solve_install(
+                                        self.image.get_frozen_list(),
+                                        update_dict,
+                                        excludes=self.__new_excludes,
+                                        reject_set=reject_set,
+                                        trim_proposed_installed=False,
+                                        ignore_inst_parent_deps=\
+                                            ignore_inst_parent_deps)
+                        else:
+                                # Updating all installed packages requires a
+                                # different solution path.
+                                new_vector, new_avoid_obs = \
+                                    solver.solve_update_all(
+                                        self.image.get_frozen_list(),
+                                        excludes=self.__new_excludes,
+                                        reject_set=reject_set)
+
+                        return solver, new_vector, new_avoid_obs
+
+                # We can't retry this operation while ignoring parent
+                # dependencies if we're doing a unconstrained update.
+                retry_wo_parent_deps = bool(pkgs_update)
+
+                # Solve; will raise exceptions if no solution is found.
+                solver, new_vector, self.pd._new_avoid_obs = \
+                    self.__run_solver(solver_cb, \
+                        retry_wo_parent_deps=retry_wo_parent_deps)
 
                 self.pd._fmri_changes = self.__vector_2_fmri_changes(
-                    installed_dict, new_vector)
+                    installed_dict, new_vector,
+                    new_facets=new_facets)
 
                 self.pd._solver_summary = str(solver)
                 if DebugValues["plan"]:
@@ -714,15 +1020,23 @@
                 """Plan reverting the specified files or files tagged as
                 specified.  We create the pkgplans here rather than in
                 evaluate; by keeping the list of changed_fmris empty we
-                skip most of the processing in evaluate"""
+                skip most of the processing in evaluate.
+                We also process revert tags on directories here"""
 
                 self.__plan_op()
 
                 revert_dict = defaultdict(list)
+                revert_dirs = defaultdict(list)
 
                 pt = self.__progtrack
                 pt.plan_all_start()
 
+                # since the fmri list stays empty, we can set this;
+                # we need this set so we can build directories and
+                # actions lists as we're doing checking with installed
+                # actions earlier here.
+                self.pd.state = plandesc.EVALUATED_PKGS
+
                 # We could have a specific 'revert' tracker item, but
                 # "package planning" seems as good a term as any.
                 pt.plan_start(pt.PLAN_PKGPLAN,
@@ -734,6 +1048,9 @@
                         # they differ from the manifests.  Note we don't care
                         # if the file is editable or not.
 
+                        # look through directories to see if any have our
+                        # revert-tag set; we then need to check the value
+                        # to find any unpackaged files that need deletion.
                         tag_set = set(args)
                         for f in self.image.gen_installed_pkgs():
                                 pt.plan_add_progress(pt.PLAN_PKGPLAN)
@@ -745,9 +1062,24 @@
                                             (set(act.attrlist("revert-tag")) &
                                              tag_set):
                                                 revert_dict[(f, m)].append(act)
+
+                                for act in m.gen_actions_by_type("dir",
+                                    self.__new_excludes):
+                                        if "revert-tag" not in act.attrs:
+                                                continue
+                                        for a in act.attrlist("revert-tag"):
+                                                tag_parts = a.split("=", 2)
+                                                if tag_parts[0] not in tag_set or \
+                                                    len(tag_parts) != 2:
+                                                        continue
+                                                revert_dirs[(f, m)].append(
+                                                    self.__gen_matching_acts(
+                                                    act.attrs["path"],
+                                                    tag_parts[1]))
                 else:
                         # look through all the packages, looking for our files
-                        # we could use search for this.
+                        # we could use search for this.  We don't support reverting
+                        # directories by ad-hoc means.
 
                         revertpaths = set([a.lstrip(os.path.sep) for a in args])
                         overlaypaths = set()
@@ -793,20 +1125,119 @@
                                 act.verify(self.image, forever=True)
                                 if act.replace_required == True:
                                         needs_change.append(act)
-                        if needs_change:
-                                pp = pkgplan.PkgPlan(self.image)
-                                pp.propose_repair(f, m, needs_change,
-                                    misc.EmptyI)
-                                pp.evaluate(self.__new_excludes,
-                                    self.__new_excludes,
-                                    can_exclude=True)
-                                self.pd.pkg_plans.append(pp)
+
+                        revert_dict[(f, m)] = needs_change
+
+                for f, m in revert_dirs:
+                        needs_delete = []
+                        for unchecked, checked in revert_dirs[(f, m)]:
+                                # just add these...
+                                needs_delete.extend(checked)
+                                # look for these
+                                for un in unchecked:
+                                        path = un.attrs["path"]
+                                        if path not in self.get_actions("file") \
+                                            and path not in self.get_actions("hardlink") \
+                                            and path not in self.get_actions("link"):
+                                                needs_delete.append(un)
+                        revert_dirs[(f, m)] = needs_delete
+
+                # build the pkg plans, making sure to propose only one repair
+                # per fmri
+                for f, m in set(revert_dirs.keys() + revert_dict.keys()):
+                        needs_delete = revert_dirs[(f, m)]
+                        needs_change = revert_dict[(f, m)]
+                        if not needs_delete and not needs_change:
+                                continue
+
+                        pp = pkgplan.PkgPlan(self.image)
+                        pp.propose_repair(f, m, needs_change, needs_delete)
+                        pp.evaluate(self.__new_excludes, self.__new_excludes,
+                            can_exclude=True)
+                        self.pd.pkg_plans.append(pp)
 
                 self.pd._fmri_changes = []
-                self.pd.state = plandesc.EVALUATED_PKGS
+
                 pt.plan_done(pt.PLAN_PKGPLAN)
                 pt.plan_all_done()
 
+        def __gen_matching_acts(self, path, pattern):
+                # return two lists of actions that match pattern at path
+                # include (recursively) directories only if they are not
+                # implicitly or explicitly packaged.  First list may
+                # contain packaged objects, second does not.
+
+                if path == os.path.sep: # not doing root
+                        return [], []
+
+                dir_loc  = os.path.join(self.image.root, path)
+
+                # If this is a mount point, disable this; too easy
+                # to break things.  This means this doesn't work
+                # on /var and /tmp - that's ok.
+
+                try:
+                        # if dir is missing, nothing to delete :)
+                        my_dev = os.stat(dir_loc).st_dev
+                except OSError:
+                        return [], []
+
+                # disallow mount points for safety's sake.
+                if my_dev != os.stat(os.path.dirname(dir_loc)).st_dev:
+                        return [], []
+
+                # Any explicit or implicitly packaged directories are
+                # ignored; checking all directory entries is cheap.
+                paths = [
+                    os.path.join(dir_loc, a)
+                    for a in fnmatch.filter(os.listdir(dir_loc), pattern)
+                    if os.path.join(path, a) not in self.__get_directories()
+                ]
+
+                # now we have list of items to be removed.  We know that
+                # any directories are not packaged, so expand those here
+                # and generate actions
+                unchecked = []
+                checked = []
+
+                for path in paths:
+                        if os.path.isdir(path) and not os.path.islink(path):
+                                # we have a directory that needs expanding;
+                                # add it in and then walk the contents
+                                checked.append(self.__gen_del_act(path))
+                                for dirpath, dirnames, filenames in os.walk(path):
+                                        # crossed mountpoints - don't go here.
+                                        if os.stat(dirpath).st_dev != my_dev:
+                                                continue
+                                        for name in dirnames + filenames:
+                                                checked.append(
+                                                    self.__gen_del_act(
+                                                    os.path.join(dirpath, name)))
+                        else:
+                                unchecked.append(self.__gen_del_act(path))
+                return unchecked, checked
+
+        def __gen_del_act(self, path):
+                # With fully qualified path, return action suitable for
+                # deletion from image. Don't bother getting owner
+                # and group right; we're just going to blow it up anyway.
+
+                rootdir = self.image.root
+                pubpath = pkg.misc.relpath(path, rootdir)
+                pstat = os.lstat(path)
+                mode = oct(stat.S_IMODE(pstat.st_mode))
+                if stat.S_ISLNK(pstat.st_mode):
+                        return pkg.actions.link.LinkAction(
+                            target=os.readlink(path), path=pubpath)
+                elif stat.S_ISDIR(pstat.st_mode):
+                        return pkg.actions.directory.DirectoryAction(
+                            mode=mode, owner="root",
+                            group="bin", path=pubpath)
+                else: # treat everything else as a file
+                        return pkg.actions.file.FileAction(
+                            mode=mode, owner="root",
+                            group="bin", path=pubpath)
+
         def plan_noop(self):
                 """Create a plan that doesn't change the package contents of
                 the current image."""
@@ -1100,10 +1531,24 @@
                 # We end up with no actions or start with one or none and end
                 # with exactly one.
                 if len(actions) == 0 or (len(oactions) <= len(actions) == 1):
+                        if (len(oactions) > 1 and
+                            any(a[0].attrs.get("overlay") == "true"
+                                for a in oactions)):
+                                # If more than one action is being removed and
+                                # one of them is an overlay, then suppress
+                                # removal of the overlaid actions (if any) to
+                                # ensure preserve rules of overlay action apply.
+                                return "overlay", None
                         return None
 
                 # Removing actions.
                 if len(actions) < len(oactions):
+                        # If any of the new actions is an overlay, suppress
+                        # the removal of the overlaid action.
+                        if any(a[0].attrs.get("overlay") == "true"
+                            for a in actions):
+                                return "overlay", None
+
                         # If we still end up in a broken state, signal the
                         # caller that we should move forward, but not remove
                         # any actions.
@@ -1314,29 +1759,82 @@
                                         self.pd.removal_actions[i] = None
                 elif msg == "overlay":
                         pp_needs_trimming = {}
+                        moved = set()
+                        # Suppress install and update of overlaid file.
                         for al in (self.pd.install_actions,
                             self.pd.update_actions):
                                 for i, ap in enumerate(al):
-                                        if not (ap and ap.dst.attrs.get(
-                                            ap.dst.key_attr, None) == key):
+                                        if not ap:
+                                                # Action has been removed.
+                                                continue
+
+                                        attrs = ap.dst.attrs
+                                        if attrs.get(ap.dst.key_attr) != key:
+                                                if ("preserve" in attrs and
+                                                    "original_name" in attrs):
+                                                        # Possible move to a
+                                                        # different location for
+                                                        # editable file.
+                                                        # Overlay attribute is
+                                                        # not checked in case it
+                                                        # was dropped as part of
+                                                        # move.
+                                                        moved.add(
+                                                            attrs["original_name"])
                                                 continue
-                                        if ap.dst.attrs.get("overlay") == \
-                                            "allow":
-                                                # Remove overlaid actions from
-                                                # plan.
-                                                al[i] = None
-                                                pp_needs_trimming.setdefault(id(ap.p),
-                                                    { "plan": ap.p, "trim": [] })
-                                                pp_needs_trimming[id(ap.p)]["trim"].append(
-                                                    id(ap.dst))
-                                                break
+
+                                        if attrs.get("overlay") != "allow":
+                                                    # Only care about overlaid
+                                                    # actions.
+                                                    continue
+
+                                        # Remove conflicting, overlaid actions
+                                        # from plan.
+                                        al[i] = None
+                                        pp_needs_trimming.setdefault(id(ap.p),
+                                            { "plan": ap.p, "trim": [] })
+                                        pp_needs_trimming[id(ap.p)]["trim"].append(
+                                            id(ap.dst))
+                                        break
+
+                        # Suppress removal of overlaid file.
+                        al = self.pd.removal_actions
+                        for i, ap in enumerate(al):
+                                if not ap:
+                                        continue
+
+                                attrs = ap.src.attrs
+                                if not attrs.get(ap.src.key_attr) == key:
+                                        continue
+
+                                if attrs.get("overlay") != "allow":
+                                        # Only interested in overlaid actions.
+                                        continue
+
+                                orig_name = attrs.get("original_name",
+                                    "%s:%s" % (ap.p.origin_fmri.get_name(),
+                                        attrs["path"]))
+                                if orig_name in moved:
+                                        # File has moved locations; removal will
+                                        # be executed, but file will be saved
+                                        # for the move skipping unlink.
+                                        ap.src.attrs["save_file"] = \
+                                            [orig_name, "false"]
+                                        break
+
+                                al[i] = None
+                                pp_needs_trimming.setdefault(id(ap.p),
+                                    { "plan": ap.p, "trim": [] })
+                                pp_needs_trimming[id(ap.p)]["trim"].append(
+                                    id(ap.src))
+                                break
 
                         for entry in pp_needs_trimming.values():
                                 p = entry["plan"]
                                 trim = entry["trim"]
                                 # Can't modify the p.actions tuple, so modify
                                 # the added member in-place.
-                                for prop in ("added", "changed"):
+                                for prop in ("added", "changed", "removed"):
                                         pval = getattr(p.actions, prop)
                                         pval[:] = [
                                             a
@@ -1374,11 +1872,53 @@
                                     []).append((a, pfmri))
                 return d
 
-        def __update_old(self, new, old, offset_dict, action_classes, sf,
-            gone_fmris, fmri_dict):
-                """Update the 'old' dictionary with all actions from the action
-                cache which could conflict with the newly actions delivered
-                actions contained in 'new.'
+        @staticmethod
+        def __act_dup_check(tgt, key, actstr, fmristr):
+                """Check for duplicate actions/fmri tuples in 'tgt', which is
+                indexed by 'key'."""
+
+                #
+                # When checking for duplicate actions we have to account for
+                # the fact that actions which are part of a package plan are
+                # not stripped.  But the actions we're iterating over here are
+                # coming from the stripped action cache, so they have had
+                # assorted attributes removed (like variants, facets, etc.) So
+                # to check for duplicates we have to make sure to strip the
+                # actions we're comparing against.  Of course we can't just
+                # strip the actions which are part of a package plan because
+                # we could be removing data critical to the execution of that
+                # action like original_name, etc.  So before we strip an
+                # action we have to make a copy of it.
+                #
+                # If we're dealing with a directory action and an "implicit"
+                # attribute exists, we need to preserve it.  We assume it's a
+                # synthetic attribute that indicates that the action was
+                # created implicitly (and hence won't conflict with an
+                # explicit directory action defining the same directory).
+                # Note that we've assumed that no one will ever add an
+                # explicit "implicit" attribute to a directory action.
+                #
+                preserve = {"dir": ["implicit"]}
+                if key not in tgt:
+                        return False
+                for act, pfmri in tgt[key]:
+                        # check the fmri first since that's easy
+                        if fmristr != str(pfmri):
+                                continue
+                        act = pkg.actions.fromstr(str(act))
+                        act.strip(preserve=preserve)
+                        if actstr == str(act):
+                                return True
+                return False
+
+        def __update_act(self, keys, tgt, skip_dups, offset_dict,
+            action_classes, sf, skip_fmris, fmri_dict):
+                """Update 'tgt' with action/fmri pairs from the stripped
+                action cache that are associated with the specified action
+                'keys'.
+
+                The 'skip_dups' parameter indicates if we should avoid adding
+                duplicate action/pfmri pairs into 'tgt'.
 
                 The 'offset_dict' parameter contains a mapping from key to
                 offsets into the actions.stripped file and the number of lines
@@ -1391,9 +1931,9 @@
                 read the actual actions indicated by the offset dictionary
                 'offset_dict.'
 
-                The 'gone_fmris' parameter contains a set of strings
-                representing the packages which are being removed from the
-                system.
+                The 'skip_fmris' parameter contains a set of strings
+                representing the packages which we should not process actions
+                for.
 
                 The 'fmri_dict' parameter is a cache of previously built PkgFmri
                 objects which is used so the same string isn't translated into
@@ -1401,7 +1941,7 @@
 
                 build_release = self.image.attrs["Build-Release"]
 
-                for key in set(itertools.chain(new.iterkeys(), old.keys())):
+                for key in keys:
                         offsets = []
                         for klass in action_classes:
                                 offset = offset_dict.get((klass.name, key),
@@ -1422,86 +1962,7 @@
                                         if line == "":
                                                 break
                                         fmristr, actstr = line.split(None, 1)
-                                        if fmristr in gone_fmris:
-                                                continue
-                                        act = pkg.actions.fromstr(actstr)
-                                        assert act.attrs[act.key_attr] == key
-                                        assert pns is None or \
-                                            act.namespace_group == pns
-                                        pns = act.namespace_group
-
-                                        try:
-                                                pfmri = fmri_dict[fmristr]
-                                        except KeyError:
-                                                pfmri = pkg.fmri.PkgFmri(
-                                                    fmristr,
-                                                    build_release)
-                                                fmri_dict[fmristr] = pfmri
-                                        old.setdefault(key, []).append(
-                                            (act, pfmri))
-
-        def __update_new(self, new, old, offset_dict, action_classes, sf,
-            gone_fmris, fmri_dict):
-                """Update 'new' with all the actions from the action cache which
-                are staying on the system and could conflict with the newly
-                installed actions.
-
-                The 'offset_dict' parameter contains a mapping from key to
-                offsets into the actions.stripped file and the number of lines
-                to read.
-
-                The 'action_classes' parameter contains the list of action types
-                where one action can conflict with another action.
-
-                The 'sf' parameter is the actions.stripped file from which we
-                read the actual actions indicated by the offset dictionary
-                'offset_dict.'
-
-                The 'gone_fmris' parameter contains a set of strings
-                representing the packages which are being removed from the
-                system.
-
-                The 'fmri_dict' parameter is a cache of previously built PkgFmri
-                objects which is used so the same string isn't translated into
-                the same PkgFmri object multiple times."""
-
-                # If we're not changing any fmris, as in the case of a
-                # change-facet/variant, revert, fix, or set-mediator, then we
-                # need to skip modifying new, as it'll just end up with
-                # incorrect duplicates.
-                if self.planned_op in (
-                    pkgdefs.API_OP_CHANGE_FACET,
-                    pkgdefs.API_OP_CHANGE_VARIANT,
-                    pkgdefs.API_OP_REPAIR,
-                    pkgdefs.API_OP_REVERT,
-                    pkgdefs.API_OP_SET_MEDIATOR):
-                        return
-
-                build_release = self.image.attrs["Build-Release"]
-
-                for key in old.iterkeys():
-                        offsets = []
-                        for klass in action_classes:
-                                offset = offset_dict.get((klass.name, key),
-                                    None)
-                                if offset is not None:
-                                        offsets.append(offset)
-
-                        for offset, cnt in offsets:
-                                sf.seek(offset)
-                                pns = None
-                                i = 0
-                                while 1:
-                                        line = sf.readline()
-                                        i += 1
-                                        if i > cnt:
-                                                break
-                                        line = line.rstrip()
-                                        if line == "":
-                                                break
-                                        fmristr, actstr = line.rstrip().split(
-                                            None, 1)
-                                        if fmristr in gone_fmris:
+                                        if fmristr in skip_fmris:
                                                 continue
                                         act = pkg.actions.fromstr(actstr)
                                         assert act.attrs[act.key_attr] == key
@@ -1515,7 +1976,10 @@
                                                 pfmri = pkg.fmri.PkgFmri(
                                                     fmristr, build_release)
                                                 fmri_dict[fmristr] = pfmri
-                                        new.setdefault(key, []).append(
+                                        if skip_dups and self.__act_dup_check(
+                                            tgt, key, actstr, fmristr):
+                                                continue
+                                        tgt.setdefault(key, []).append(
                                             (act, pfmri))
 
         def __fast_check(self, new, old, ns):
@@ -1677,6 +2141,32 @@
                                     errs):
                                         continue
 
+                # Ensure that overlay and preserve file semantics are handled
+                # as expected when conflicts only exist in packages that are
+                # being removed.
+                for key, oactions in old.iteritems():
+                        self.__progtrack.plan_add_progress(
+                            self.__progtrack.PLAN_ACTION_CONFLICT)
+
+                        if len(oactions) < 2:
+                                continue
+
+                        if key in new:
+                                # Already processed.
+                                continue
+
+                        if any(a[0].name != "file" for a in oactions):
+                                continue
+
+                        entry = oactions[0][0]
+                        if not entry.refcountable and entry.globally_identical:
+                                if self.__process_conflicts(key,
+                                    self.__check_duplicate_actions,
+                                    [], oactions,
+                                    api_errors.DuplicateActionError,
+                                    errs):
+                                        continue
+
         @staticmethod
         def _check_actions(nsd):
                 """Return the keys in the namespace dictionary ('nsd') which
@@ -1759,11 +2249,20 @@
                         self.__clear_pkg_plans()
                         return
 
+                # figure out which installed packages are being removed by
+                # this operation
                 old_fmris = set((
                     str(s) for s in self.image.gen_installed_pkgs()
                 ))
                 gone_fmris = old_fmris - new_fmris
 
+                # figure out which new packages are being touched by this
+                # operation.
+                changing_fmris = set([
+                        str(p.destination_fmri)
+                        for p in self.pd.pkg_plans
+                        if p.destination_fmri
+                ])
 
                 # Group action types by namespace groups
                 kf = operator.attrgetter("namespace_group")
@@ -1819,15 +2318,20 @@
                                 # cache which could conflict with the new
                                 # actions being installed, or with actions
                                 # already installed, but not getting removed.
-                                self.__update_old(new, old, offset_dict,
-                                    action_classes, msf, gone_fmris, fmri_dict)
+                                keys = set(itertools.chain(new.iterkeys(),
+                                    old.iterkeys()))
+                                self.__update_act(keys, old, False,
+                                    offset_dict, action_classes, msf,
+                                    gone_fmris, fmri_dict)
 
                                 # Now update 'new' with all actions from the
                                 # action cache which are staying on the system,
                                 # and could conflict with the actions being
                                 # installed.
-                                self.__update_new(new, old, offset_dict,
-                                    action_classes, msf, gone_fmris, fmri_dict)
+                                keys = set(old.iterkeys())
+                                self.__update_act(keys, new, True,
+                                    offset_dict, action_classes, msf,
+                                    gone_fmris | changing_fmris, fmri_dict)
 
                         self.__check_conflicts(new, old, action_classes, ns,
                             errs)
@@ -1980,6 +2484,16 @@
                 self.merge_actions()
                 self.compile_release_notes()
 
+                fmri_updates = [
+                        (p.origin_fmri, p.destination_fmri)
+                        for p in self.pd.pkg_plans
+                ]
+                if not self.pd._li_pkg_updates and fmri_updates:
+                        # oops.  the caller requested no package updates and
+                        # we couldn't satisfy that request.
+                        raise api_errors.PlanCreationException(
+                            pkg_updates_required=fmri_updates)
+
                 for p in self.pd.pkg_plans:
                         cpbytes, pbytes = p.get_bytes_added()
                         if p.destination_fmri:
@@ -2052,7 +2566,7 @@
                                 if str(pfmri.version) == "0,5.11" \
                                     and containing_fmri.pkg_name \
                                     not in installed_dict:
-                                                return True
+                                        return True
                                 else:
                                         pfmri.pkg_name = \
                                             containing_fmri.pkg_name
@@ -2083,15 +2597,15 @@
                         installed_dict = ImagePlan.__fmris2dict(
                             self.image.gen_installed_pkgs())
                         for act, pfmri in release_notes:
-                                if self.__include_note(installed_dict, act, 
+                                if self.__include_note(installed_dict, act,
                                     pfmri):
-                                        if act.attrs.get("must-display", 
+                                        if act.attrs.get("must-display",
                                             "false") == "true":
                                                 must_display = True
                                         for l in self.__get_note_text(
                                             act, pfmri).splitlines():
                                                 notes.append(misc.decode(l))
-                                        
+
                         self.pd.release_notes = (must_display, notes)
 
         def save_release_notes(self):
@@ -2106,7 +2620,9 @@
                         for note in self.pd.release_notes[1]:
                                 if isinstance(note, unicode):
                                         note = note.encode("utf-8")
-                                print >>tmpfile, note
+                                print >> tmpfile, note
+			# make file world readable
+			os.chmod(path, 0644)
                         tmpfile.close()
                         self.pd.release_notes_name = os.path.basename(path)
 
@@ -2202,6 +2718,19 @@
                 on the metadata of the links that are still or will be installed.
                 Returns a dictionary of the proposed mediations."""
 
+                #
+                # If we're not changing mediators, and we're not changing
+                # variants or facets (which could affect mediators), and we're
+                # not changing any packages (which could affect mediators),
+                # then mediators can't be changing so there's nothing to do
+                # here.
+                #
+                if not self.pd._mediators_change and \
+                    not self.pd._varcets_change and \
+                    not self.pd._fmri_changes:
+                        # return the currently configured mediators
+                        return defaultdict(set, self.pd._cfg_mediators)
+
                 prop_mediators = defaultdict(set)
                 mediated_installed_paths = defaultdict(set)
                 for a, pfmri in itertools.chain(
@@ -2850,8 +3379,15 @@
                                         del cons_generic[("file", ra.attrs["path"])]
                                         dest_pkgplans[id(ap.dst)] = ap.p
                                 else:
-                                        ra.attrs["save_file"] = cache_name
-                                        ap.dst.attrs["save_file"] = cache_name
+                                        # The 'true' indicates the file should
+                                        # be removed from source.  The removal
+                                        # action is changed using setdefault so
+                                        # that any overlay rules applied during
+                                        # conflict checking remain intact.
+                                        ra.attrs.setdefault("save_file",
+                                            [cache_name, "true"])
+                                        ap.dst.attrs["save_file"] = [cache_name,
+                                            "true"]
 
                                 cache_name = index = ra = None
 
@@ -2960,8 +3496,13 @@
                 pt.plan_start(pt.PLAN_ACTION_FINALIZE)
 
                 # Go over update actions
-                l_actions = self.get_actions("hardlink", self.hardlink_keyfunc)
                 l_refresh = []
+                l_actions = {}
+                if self.pd.update_actions:
+                        # iterating over actions is slow, so don't do it
+                        # unless we have to.
+                        l_actions = self.get_actions("hardlink",
+                            self.hardlink_keyfunc)
                 for a in self.pd.update_actions:
                         # For any files being updated that are the target of
                         # _any_ hardlink actions, append the hardlink actions
@@ -2996,14 +3537,28 @@
                 self.pd.update_actions.sort(key=addsort)
                 self.pd.install_actions.sort(key=addsort)
 
+                # cleanup pkg_plan objects which don't actually contain any
+                # changes
+                for p in list(self.pd.pkg_plans):
+                        if p.origin_fmri != p.destination_fmri or \
+                            p.actions.removed or p.actions.changed or \
+                            p.actions.added:
+                                continue
+                        self.pd.pkg_plans.remove(p)
+                        fmri = p.origin_fmri
+                        if (fmri, fmri) in self.pd._fmri_changes:
+                                self.pd._fmri_changes.remove(
+                                    (fmri, fmri))
+                        del p
+
                 #
                 # Sort the package plans by fmri to create predictability (and
                 # some sense of order) in the download output; this is not
-		# a perfect sort of this, but we only really care for things
-		# we fetch over the wire.
+                # a perfect sort of this, but we only really care for things
+                # we fetch over the wire.
                 #
                 self.pd.pkg_plans.sort(
-		    key=operator.attrgetter("destination_fmri"))
+                    key=operator.attrgetter("destination_fmri"))
 
                 pt.plan_done(pt.PLAN_ACTION_FINALIZE)
 
@@ -3127,7 +3682,7 @@
 
                 #
                 # Calculate size of data retrieval and pass it to progress
-		# tracker.
+                # tracker.
                 #
                 npkgs = nfiles = nbytes = 0
                 for p in self.pd.pkg_plans:
--- a/src/modules/client/linkedimage/common.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/linkedimage/common.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """
@@ -59,6 +59,7 @@
 import pkg.client.pkgplan as pkgplan
 import pkg.client.pkgremote
 import pkg.client.progress as progress
+import pkg.facet
 import pkg.fmri
 import pkg.misc as misc
 import pkg.pkgsubprocess
@@ -107,6 +108,7 @@
 
 # files which contain linked image data
 __DATA_DIR     = "linked"
+PATH_PFACETS    = os.path.join(__DATA_DIR, "linked_pfacets")
 PATH_PPKGS     = os.path.join(__DATA_DIR, "linked_ppkgs")
 PATH_PROP      = os.path.join(__DATA_DIR, "linked_prop")
 PATH_PUBS      = os.path.join(__DATA_DIR, "linked_ppubs")
@@ -409,6 +411,7 @@
                 self.__props = dict()
                 self.__ppkgs = frozenset()
                 self.__ppubs = None
+                self.__pfacets = pkg.facet.Facets()
                 self.__pimg = None
 
                 # variables reset by self.__recursion_init()
@@ -420,6 +423,8 @@
                 self.__path_ppkgs = None
                 self.__path_prop = None
                 self.__path_ppubs = None
+                self.__path_pfacets = None
+                self.__img_insync = True
 
                 # initialize with no properties
                 self.__update_props()
@@ -469,9 +474,20 @@
                 self.__path_ppkgs = os.path.join(imgdir, PATH_PPKGS)
                 self.__path_prop = os.path.join(imgdir, PATH_PROP)
                 self.__path_ppubs = os.path.join(imgdir, PATH_PUBS)
+                self.__path_pfacets = os.path.join(imgdir, PATH_PFACETS)
 
                 # if this isn't a reset, then load data from the image
                 if not old_root:
+                        # the first time around we load non-temporary data (if
+                        # there is any) so that we can audit ourselves and see
+                        # if we're in currently in sync.
+                        self.__load(tmp=False)
+                        if self.ischild():
+                                self.__img_insync = self.__insync()
+
+                        # now re-load all the data taking into account any
+                        # temporary new data associated with an in-progress
+                        # operation.
                         self.__load()
 
                 # we're not linked or we're not changing root paths we're done
@@ -513,6 +529,7 @@
                 self.__props = props
                 self.__ppkgs = frozenset()
                 self.__ppubs = None
+                self.__pfacets = pkg.facet.Facets()
                 self.__pimg = None
 
         def __verify_props(self, props):
@@ -707,30 +724,57 @@
                 self.__verify_props(props)
                 return props
 
-        def __load_ondisk_ppkgs(self, tmp=True):
-                """Load linked image parent constraints from disk.
+        def __load_ondisk_pfacets(self, tmp=True):
+                """Load linked image inherited facets from disk.
                 Don't update any internal state.
 
                 'tmp' determines if we should read/write to the official
                 linked image metadata files, or if we should access temporary
                 versions (which have ".<runid>" appended to them."""
 
+                pfacets = misc.EmptyDict
+                path = "%s.%d" % (self.__path_pfacets,
+                    global_settings.client_runid)
+                if tmp and path_exists(path):
+                        pfacets = load_data(path)
+                else:
+                        path = self.__path_pfacets
+                        pfacets = load_data(path, missing_ok=True)
+
+                if pfacets is None:
+                        return None
+
+                rv = pkg.facet.Facets()
+                for k, v in pfacets.iteritems():
+                        # W0212 Access to a protected member
+                        # pylint: disable=W0212
+                        rv._set_inherited(k, v)
+                return rv
+
+        def __load_ondisk_ppkgs(self, tmp=True):
+                """Load linked image parent packages from disk.
+                Don't update any internal state.
+
+                'tmp' determines if we should read/write to the official
+                linked image metadata files, or if we should access temporary
+                versions (which have ".<runid>" appended to them."""
+
+                fmri_strs = None
                 path = "%s.%d" % (self.__path_ppkgs,
                     global_settings.client_runid)
                 if tmp and path_exists(path):
-                        return frozenset([
-                            pkg.fmri.PkgFmri(str(s))
-                            for s in load_data(path, missing_val=misc.EmptyI)
-                        ])
-
-                path = self.__path_ppkgs
-                if path_exists(path):
-                        return frozenset([
-                            pkg.fmri.PkgFmri(str(s))
-                            for s in load_data(path, missing_val=misc.EmptyI)
-                        ])
-
-                return None
+                        fmri_strs = load_data(path)
+                else:
+                        path = self.__path_ppkgs
+                        fmri_strs = load_data(path, missing_ok=True)
+
+                if fmri_strs is None:
+                        return None
+
+                return frozenset([
+                    pkg.fmri.PkgFmri(str(s))
+                    for s in fmri_strs
+                ])
 
         def __load_ondisk_ppubs(self, tmp=True):
                 """Load linked image parent publishers from disk.
@@ -740,18 +784,18 @@
                 linked image metadata files, or if we should access temporary
                 versions (which have ".<runid>" appended to them."""
 
+                ppubs = None
                 path = "%s.%d" % (self.__path_ppubs,
                     global_settings.client_runid)
                 if tmp and path_exists(path):
-                        return load_data(path)
-
-                path = self.__path_ppubs
-                if path_exists(path):
-                        return load_data(path)
-
-                return None
-
-        def __load(self):
+                        ppubs = load_data(path)
+                else:
+                        path = self.__path_ppubs
+                        ppubs = load_data(path, missing_ok=True)
+
+                return ppubs
+
+        def __load(self, tmp=True):
                 """Load linked image properties and constraints from disk.
                 Update the linked image internal state with the loaded data."""
 
@@ -772,7 +816,7 @@
                 # and the caller will have to specify that they want to ignore
                 # all children to allow the operation to succeed.
                 #
-                props = self.__load_ondisk_props()
+                props = self.__load_ondisk_props(tmp=tmp)
                 if not props and not self.__isparent(ignore_errors=True):
                         # we're not linked
                         return
@@ -792,16 +836,25 @@
 
                 self.__update_props(props)
 
-                ppkgs = self.__load_ondisk_ppkgs()
-                if self.ischild() and ppkgs == None:
-                        _rterr(li=self, err="Constraints data missing.")
-                if self.ischild():
+                if not self.ischild():
+                        return
+
+                # load parent packages. if parent package data is missing just
+                # continue along and hope for the best.
+                ppkgs = self.__load_ondisk_ppkgs(tmp=tmp)
+                if ppkgs is not None:
                         self.__ppkgs = ppkgs
 
+                # load inherited facets. if inherited facet data is missing
+                # just continue along and hope for the best.
+                pfacets = self.__load_ondisk_pfacets(tmp=tmp)
+                if pfacets is not None:
+                        self.__pfacets = pfacets
+
                 # load parent publisher data. if publisher data is missing
                 # continue along and we'll just skip the publisher checks,
                 # it's better than failing and preventing any image updates.
-                self.__ppubs = self.__load_ondisk_ppubs()
+                self.__ppubs = self.__load_ondisk_ppubs(tmp=tmp)
 
         @staticmethod
         def __validate_prop_recurse(v):
@@ -886,6 +939,21 @@
                 differs then there is stuff to do since the new state needs
                 to be saved to disk."""
 
+                # check if we're not a linked image.
+                if not self.isparent() and not self.ischild():
+                        # if any linked image metadata files exist they need
+                        # to be deleted.
+                        paths = [
+                            self.__path_pfacets,
+                            self.__path_ppkgs,
+                            self.__path_ppubs,
+                            self.__path_prop,
+                        ]
+                        for path in paths:
+                                if path_exists(path):
+                                        return False
+                        return True
+
                 # compare in-memory and on-disk properties
                 li_ondisk_props = self.__load_ondisk_props(tmp=False)
                 if li_ondisk_props == None:
@@ -898,10 +966,35 @@
                 if li_ondisk_props != li_inmemory_props:
                         return False
 
-                # compare in-memory and on-disk constraints
+                # linked image metadata files with inherited data
+                paths = [
+                    self.__path_pfacets,
+                    self.__path_ppkgs,
+                    self.__path_ppubs,
+                ]
+
+                # check if we're just a parent image.
+                if not self.ischild():
+                        # parent images only have properties.  if any linked
+                        # image metadata files that contain inherited
+                        # information exist they need to be deleted.
+                        for path in paths:
+                                if path_exists(path):
+                                        return False
+                        return True
+
+                # if we're missing any metadata files then there's work todo
+                for path in paths:
+                        if not path_exists(path):
+                                return False
+
+                # compare in-memory and on-disk inherited facets
+                li_ondisk_pfacets = self.__load_ondisk_pfacets(tmp=False)
+                if self.__pfacets != li_ondisk_pfacets:
+                        return False
+
+                # compare in-memory and on-disk parent packages
                 li_ondisk_ppkgs = self.__load_ondisk_ppkgs(tmp=False)
-                if li_ondisk_ppkgs == None:
-                        li_ondisk_ppkgs = frozenset()
                 if self.__ppkgs != li_ondisk_ppkgs:
                         return False
 
@@ -912,34 +1005,6 @@
 
                 return True
 
-        def get_pubs(self, img=None):
-                """Return publisher information for the specified image.  If
-                no image is specified we return publisher information for the
-                current image.
-
-                Publisher information is returned in a sorted list of lists
-                of the format:
-                        <publisher name>, <sticky>
-
-                Where:
-                        <publisher name> is a string
-                        <sticky> is a boolean
-
-                The tuples are sorted by publisher rank.
-                """
-
-                # default to ourselves
-                if img == None:
-                        img = self.__img
-
-                # get a sorted list of the images publishers
-                pubs = img.get_sorted_publishers(inc_disabled=False)
-
-                rv = []
-                for p in pubs:
-                        rv.append([str(p), p.sticky])
-                return rv
-
         def pubcheck(self):
                 """If we're a child image's, verify that the parent image
                 publisher configuration is a subset of the child images
@@ -962,7 +1027,7 @@
                 if self.__img.cfg.get_policy("use-system-repo"):
                         return
 
-                pubs = self.get_pubs()
+                pubs = get_pubs(self.__img)
                 ppubs = self.__ppubs
 
                 if ppubs == None:
@@ -982,7 +1047,7 @@
                         raise apx.PlanCreationException(
                             linked_pub_error=(pubs, ppubs))
 
-        def syncmd_from_parent(self, api_op=None):
+        def __syncmd_from_parent(self):
                 """Update linked image constraint, publisher data, and
                 state from our parent image."""
 
@@ -999,41 +1064,35 @@
                         path = self.__props[PROP_PARENT_PATH]
                         self.__pimg = self.__init_pimg(path)
 
-                # generate new constraints
-                cati = self.__pimg.get_catalog(self.__img.IMG_CATALOG_INSTALLED)
-                ppkgs = frozenset(cati.fmris())
-
-                # generate new publishers
-                ppubs = self.get_pubs(img=self.__pimg)
-
-                # check if anything has changed
-                need_sync = False
-
-                if self.__ppkgs != ppkgs:
-                        # we have new constraints
-                        self.__ppkgs = ppkgs
-                        need_sync = True
-
-                if self.__ppubs != ppubs:
-                        # parent has new publishers
-                        self.__ppubs = ppubs
-                        need_sync = True
-
-                if not need_sync:
-                        # nothing changed
-                        return
-
-                # if we're not planning an image attach operation then write
-                # the linked image metadata to disk.
-                if api_op != pkgdefs.API_OP_ATTACH:
-                        self.syncmd()
+                # get metadata from our parent image
+                self.__ppubs = get_pubs(self.__pimg)
+                self.__ppkgs = get_packages(self.__pimg)
+                self.__pfacets = get_inheritable_facets(self.__pimg)
+
+        def syncmd_from_parent(self, catch_exception=False):
+                """Update linked image constraint, publisher data, and state
+                from our parent image.  If catch_exception is true catch any
+                linked image exceptions and pack them up in a linked image
+                return value tuple."""
+
+                try:
+                        self.__syncmd_from_parent()
+                except apx.LinkedImageException, e:
+                        if not catch_exception:
+                                raise e
+                        return LI_RVTuple(e.lix_exitrv, e, None)
+                return
 
         def syncmd(self):
                 """Write in-memory linked image state to disk."""
 
                 # create a list of metadata file paths
-                paths = [self.__path_ppkgs, self.__path_prop,
-                    self.__path_ppubs]
+                paths = [
+                    self.__path_pfacets,
+                    self.__path_ppkgs,
+                    self.__path_ppubs,
+                    self.__path_prop,
+                ]
 
                 # cleanup any temporary files
                 for path in paths:
@@ -1055,11 +1114,14 @@
                 save_data(self.__path_prop, props)
 
                 if not self.ischild():
-                        # if we're not a child we don't have constraints
+                        # if we're not a child we don't have parent data
+                        path_unlink(self.__path_pfacets, noent_ok=True)
                         path_unlink(self.__path_ppkgs, noent_ok=True)
+                        path_unlink(self.__path_ppubs, noent_ok=True)
                         return
 
                 # we're a child so save our latest constraints
+                save_data(self.__path_pfacets, self.__pfacets)
                 save_data(self.__path_ppkgs, self.__ppkgs)
                 save_data(self.__path_ppubs, self.__ppubs)
 
@@ -1151,6 +1213,10 @@
                 for lin in lin_list:
                         self.__verify_child_name(lin, raise_except=True)
 
+        def inherited_facets(self):
+                """Facets inherited from our parent image."""
+                return self.__pfacets
+
         def parent_fmris(self):
                 """A set of the fmris installed in our parent image."""
 
@@ -1399,7 +1465,7 @@
                                 return False
                 return True
 
-        def audit_self(self, li_parent_sync=True):
+        def audit_self(self, latest_md=True):
                 """If the current image is a child image, this function
                 audits the current image to see if it's in sync with its
                 parent."""
@@ -1408,14 +1474,17 @@
                         e = self.__apx_not_child()
                         return LI_RVTuple(pkgdefs.EXIT_OOPS, e, None)
 
-                try:
-                        if li_parent_sync:
-                                # try to refresh linked image constraints from
-                                # the parent image.
-                                self.syncmd_from_parent()
-
-                except apx.LinkedImageException, e:
-                        return LI_RVTuple(e.lix_exitrv, e, None)
+                if not latest_md:
+                        # we don't use the latest linked image metadata.
+                        # instead return cached insync value which was
+                        # computed using the initial linked image metadata
+                        # that we loaded from disk.
+                        if not self.__img_insync:
+                                e = apx.LinkedImageException(
+                                    child_diverged=self.child_name)
+                                return LI_RVTuple(pkgdefs.EXIT_DIVERGED, e,
+                                    None)
+                        return LI_RVTuple(pkgdefs.EXIT_OK, None, None)
 
                 if not self.__insync():
                         e = apx.LinkedImageException(
@@ -1424,6 +1493,16 @@
 
                 return LI_RVTuple(pkgdefs.EXIT_OK, None, None)
 
+        def insync(self, latest_md=True):
+                """A convenience wrapper for audit_self().  Note that we
+                consider non-child images as always in sync and ignore
+                any runtime errors."""
+
+                rv = self.image.linked.audit_self(latest_md=latest_md)[0]
+                if rv == pkgdefs.EXIT_DIVERGED:
+                        return False
+                return True
+
         @staticmethod
         def __rvdict2rv(rvdict, rv_map=None):
                 """Internal helper function that takes a dictionary returned
@@ -1711,8 +1790,8 @@
                     _progtrack=progtrack,
                     _failfast=False,
                     _expect_plan=True,
+                    _syncmd_tmp=True,
                     accept=accept,
-                    li_attach_sync=True,
                     li_md_only=li_md_only,
                     li_pkg_updates=li_pkg_updates,
                     noexecute=noexecute,
@@ -1761,7 +1840,7 @@
                     _failfast=False))
                 return rvdict
 
-        def sync_children(self, lin_list, accept=False, li_attach_sync=False,
+        def sync_children(self, lin_list, accept=False,
             li_md_only=False, li_pkg_updates=True, progtrack=None,
             noexecute=False, refresh_catalogs=True, reject_list=misc.EmptyI,
             show_licenses=False, update_index=True):
@@ -1775,6 +1854,10 @@
 
                 lic_dict = self.__children_init(lin_list=lin_list)
 
+                _syncmd_tmp = True
+                if not noexecute and li_md_only:
+                        _syncmd_tmp = False
+
                 rvdict = {}
                 list(self.__children_op(
                     _pkg_op=pkgdefs.PKG_OP_SYNC,
@@ -1783,8 +1866,8 @@
                     _progtrack=progtrack,
                     _failfast=False,
                     _expect_plan=True,
+                    _syncmd_tmp=_syncmd_tmp,
                     accept=accept,
-                    li_attach_sync=li_attach_sync,
                     li_md_only=li_md_only,
                     li_pkg_updates=li_pkg_updates,
                     noexecute=noexecute,
@@ -1794,7 +1877,8 @@
                     update_index=update_index))
                 return rvdict
 
-        def detach_children(self, lin_list, force=False, noexecute=False):
+        def detach_children(self, lin_list, force=False, noexecute=False,
+            li_md_only=False, li_pkg_updates=True):
                 """Detach one or more children from the current image. This
                 operation results in the removal of any constraint package
                 from the child images."""
@@ -1827,6 +1911,8 @@
                     _rvdict=rvdict,
                     _progtrack=progress.NullProgressTracker(),
                     _failfast=False,
+                    li_md_only=li_md_only,
+                    li_pkg_updates=li_pkg_updates,
                     noexecute=noexecute))
 
                 # if any of the children successfully detached, then we want
@@ -1860,9 +1946,9 @@
 
                 return rvdict
 
-        @staticmethod
-        def __children_op(_pkg_op, _lic_list, _rvdict, _progtrack, _failfast,
-            _expect_plan=False, _ignore_syncmd_nop=True, _pd=None, **kwargs):
+        def __children_op(self, _pkg_op, _lic_list, _rvdict, _progtrack,
+            _failfast, _expect_plan=False, _ignore_syncmd_nop=True,
+            _syncmd_tmp=False, _pd=None, **kwargs):
                 """An iterator function which performs a linked image
                 operation on multiple children in parallel.
 
@@ -1890,6 +1976,10 @@
                 always recurse into a child even if the linked image meta data
                 isn't changing.
 
+                '_syncmd_tmp' a boolean that indicates if we should write
+                linked image metadata in a temporary location in child images,
+                or just overwrite any existing data.
+
                 '_pd' a PlanDescription pointer."""
 
                 if _lic_list:
@@ -1897,17 +1987,38 @@
 
                 if _pkg_op in [ pkgdefs.PKG_OP_AUDIT_LINKED,
                     pkgdefs.PKG_OP_PUBCHECK ]:
-                        # these operations are cheap, use full parallelism
-                        concurrency = -1
+                        # these operations are cheap so ideally we'd like to
+                        # use full parallelism.  but if the user specified a
+                        # concurrency limit we should respect that.
+                        if global_settings.client_concurrency_set:
+                                concurrency = global_settings.client_concurrency
+                        else:
+                                # no limit was specified, use full concurrency
+                                concurrency = -1
                 else:
                         concurrency = global_settings.client_concurrency
 
+                # If we have a plan for the current image that means linked
+                # image metadata is probably changing so we always save it to
+                # a temporary file (and we don't overwrite the existing
+                # metadata until after we execute the plan).
+                if _pd is not None:
+                        _syncmd_tmp = True
+
+                # get parent metadata common to all child images
+                _pmd = None
+                if _pkg_op != pkgdefs.PKG_OP_DETACH:
+                        ppubs = get_pubs(self.__img)
+                        ppkgs = get_packages(self.__img, pd=_pd)
+                        pfacets = get_inheritable_facets(self.__img, pd=_pd)
+                        _pmd = (ppubs, ppkgs, pfacets)
+
                 # setup operation for each child
                 lic_setup = []
                 for lic in _lic_list:
                         try:
-                                lic.child_op_setup(_pkg_op, _progtrack,
-                                    _ignore_syncmd_nop, _pd, **kwargs)
+                                lic.child_op_setup(_pkg_op, _pmd, _progtrack,
+                                    _ignore_syncmd_nop, _syncmd_tmp, **kwargs)
                                 lic_setup.append(lic)
                         except apx.LinkedImageException, e:
                                 _rvdict[lic.child_name] = \
@@ -2011,8 +2122,19 @@
                                 _progtrack.li_recurse_status(lin_running,
                                     done)
 
-                        rlistrv = select.select(lic_running, [], [])[0]
-                        for lic in rlistrv:
+                        # poll on all the linked image children and see which
+                        # ones have pending output.
+                        fd_hash = dict([
+                            (lic.fileno(), lic)
+                            for lic in lic_running
+                        ])
+                        p = select.poll()
+                        for fd in fd_hash.keys():
+                                p.register(fd, select.POLLIN)
+                        events = p.poll()
+                        lic_list = [ fd_hash[event[0]] for event in events ]
+
+                        for lic in lic_list:
                                 _progtrack.li_recurse_progress(lic.child_name)
                                 if not lic.child_op_is_done():
                                         continue
@@ -2169,7 +2291,7 @@
                 # changing.  (this would be required for recursive operations,
                 # update operations, etc.)
                 _ignore_syncmd_nop = True
-                if pkg_op == pkgdefs.API_OP_SYNC:
+                if pd.child_op_implicit:
                         # the exception is if we're doing an implicit sync.
                         # to improve performance we assume the child is
                         # already in sync, so if its linked image metadata
@@ -2224,12 +2346,16 @@
                 # of specific packages, etc, then when we recurse we'll do a
                 # sync in the child.
                 #
+                implicit = False
                 if api_op == pkgdefs.API_OP_UPDATE and not \
                     api_kwargs["pkgs_update"]:
                         pkg_op = pkgdefs.PKG_OP_UPDATE
+                elif api_op == pkgdefs.API_OP_SYNC:
+                        pkg_op = pkgdefs.PKG_OP_SYNC
                 else:
                         pkg_op = pkgdefs.PKG_OP_SYNC
-                return pkg_op
+                        implicit = True
+                return pkg_op, implicit
 
         @staticmethod
         def __recursion_args(pd, refresh_catalogs, update_index, api_kwargs):
@@ -2275,7 +2401,8 @@
                 api_op = pd.plan_type
 
                 # update the plan arguments
-                pd.child_op = self.__recursion_op(api_op, api_kwargs)
+                pd.child_op, pd.child_op_implicit = \
+                    self.__recursion_op(api_op, api_kwargs)
                 pd.child_kwargs = self.__recursion_args(pd,
                     refresh_catalogs, update_index, api_kwargs)
                 pd.children_ignored = self.__lic_ignore
@@ -2301,6 +2428,7 @@
                 pd.li_props = self.__props
                 pd.li_ppkgs = self.__ppkgs
                 pd.li_ppubs = self.__ppubs
+                pd.li_pfacets = self.__pfacets
 
         def setup_plan(self, pd):
                 """Reload a previously created plan."""
@@ -2309,6 +2437,7 @@
                 self.__update_props(pd.li_props)
                 self.__ppubs = pd.li_ppubs
                 self.__ppkgs = pd.li_ppkgs
+                self.__pfacets = pd.li_pfacets
 
                 # now initialize our recursion state, this involves allocating
                 # handles to operate on children.  we don't need handles for
@@ -2504,6 +2633,7 @@
                 self.__path_ppkgs = os.path.join(imgdir, PATH_PPKGS)
                 self.__path_prop = os.path.join(imgdir, PATH_PROP)
                 self.__path_ppubs = os.path.join(imgdir, PATH_PUBS)
+                self.__path_pfacets = os.path.join(imgdir, PATH_PFACETS)
 
                 # initialize a linked image child plugin
                 self.__plugin = \
@@ -2572,37 +2702,29 @@
 
                 return True
 
-        def __push_ppkgs(self, tmp=False, test=False, pd=None):
+        def __push_ppkgs(self, ppkgs, tmp=False, test=False):
                 """Sync linked image parent constraint data to a child image.
 
                 'tmp' determines if we should read/write to the official
                 linked image metadata files, or if we should access temporary
                 versions (which have ".<runid>" appended to them."""
 
-                # there has to be an image plan to export
-                cati = self.__img.get_catalog(self.__img.IMG_CATALOG_INSTALLED)
-                ppkgs = set(cati.fmris())
-
-                if pd is not None:
-                        # if there's an image plan the we need to update the
-                        # installed packages based on that plan.
-                        for src, dst in pd.plan_desc:
-                                if src == dst:
-                                        continue
-                                if src:
-                                        assert src in ppkgs
-                                        ppkgs -= set([src])
-                                if dst:
-                                        assert dst not in ppkgs
-                                        ppkgs |= set([dst])
-
-                # paranoia
-                ppkgs = frozenset(ppkgs)
-
-                # save the planned cips
+                # save the planned parent packages
                 return self.__push_data(self.child_path, self.__path_ppkgs,
                     ppkgs, tmp, test)
 
+        def __push_pfacets(self, pfacets, tmp=False, test=False):
+                """Sync linked image parent facet data to a child image.
+
+                'tmp' determines if we should read/write to the official
+                linked image metadata files, or if we should access temporary
+                versions (which have ".<runid>" appended to them."""
+
+                # save the planned parent facets
+                return self.__push_data(self.child_path, self.__path_pfacets,
+                    pfacets, tmp, test)
+
+
         def __push_props(self, tmp=False, test=False):
                 """Sync linked image properties data to a child image.
 
@@ -2622,40 +2744,46 @@
                 return self.__push_data(self.child_path, self.__path_prop,
                     props, tmp, test)
 
-        def __push_ppubs(self, tmp=False, test=False):
+        def __push_ppubs(self, ppubs, tmp=False, test=False):
                 """Sync linked image parent publisher data to a child image.
 
                 'tmp' determines if we should read/write to the official
                 linked image metadata files, or if we should access temporary
                 versions (which have ".<runid>" appended to them."""
 
-                ppubs = self.__linked.get_pubs()
                 return self.__push_data(self.child_path, self.__path_ppubs,
                     ppubs, tmp, test)
 
-        def __syncmd(self, tmp=False, test=False, pd=None):
+        def __syncmd(self, pmd, tmp=False, test=False):
                 """Sync linked image data to a child image.
 
                 'tmp' determines if we should read/write to the official
                 linked image metadata files, or if we should access temporary
                 versions (which have ".<runid>" appended to them."""
 
-                if pd:
-                        tmp = True
-
-                ppkgs_updated = self.__push_ppkgs(tmp, test, pd=pd)
+                # unpack parent metadata tuple
+                ppubs, ppkgs, pfacets = pmd
+
+                ppkgs_updated = self.__push_ppkgs(ppkgs, tmp, test)
                 props_updated = self.__push_props(tmp, test)
-                pubs_updated = self.__push_ppubs(tmp, test)
-
-                return (props_updated or ppkgs_updated or pubs_updated)
-
-        def __child_op_setup_syncmd(self, ignore_syncmd_nop=True,
-            tmp=False, test=False, pd=None, stage=pkgdefs.API_STAGE_DEFAULT):
+                pubs_updated = self.__push_ppubs(ppubs, tmp, test)
+                pfacets_updated = self.__push_pfacets(pfacets, tmp, test)
+
+                return (props_updated or ppkgs_updated or pubs_updated or
+                    pfacets_updated)
+
+        def __child_op_setup_syncmd(self, pmd, ignore_syncmd_nop=True,
+            tmp=False, test=False, stage=pkgdefs.API_STAGE_DEFAULT):
                 """Prepare to perform an operation on a child image by syncing
                 the latest linked image data to that image.  As part of this
                 operation, if we discover that the meta data hasn't changed we
                 may report back that there is nothing to do (EXIT_NOP).
 
+                'pmd' is a tuple that contains parent metadata that we will
+                sync to the child image.  Note this is not all the metadata
+                that we will sync, just the set which is common to all
+                children.
+
                 'ignore_syncmd_nop' a boolean that indicates if we should
                 always recurse into a child even if the linked image meta data
                 isn't changing.
@@ -2668,23 +2796,16 @@
                 image meta data, instead we should just test to see if the
                 meta data is changing.
 
-                'pd' an optional plan description object.  this plan
-                description describes changes that will be made to the parent
-                image.  if this is supplied then we derive the meta data that
-                we write into the child from the planned parent image state
-                (instead of the current parent image state).
-
                 'stage' indicates which stage of execution we should be
                 performing on a child image."""
 
-                # we don't actually update metadata during other stages of
-                # operation
+                # we don't update metadata during all stages of operation
                 if stage not in [
                     pkgdefs.API_STAGE_DEFAULT, pkgdefs.API_STAGE_PLAN]:
                         return True
 
                 try:
-                        updated = self.__syncmd(tmp=tmp, test=test, pd=pd)
+                        updated = self.__syncmd(pmd, tmp=tmp, test=test)
                 except apx.LinkedImageException, e:
                         self.__child_op_rvtuple = \
                             LI_RVTuple(e.lix_exitrv, e, None)
@@ -2703,9 +2824,9 @@
                     LI_RVTuple(pkgdefs.EXIT_NOP, None, None)
                 return False
 
-        def __child_setup_sync(self, _progtrack, _ignore_syncmd_nop, _pd,
+        def __child_setup_sync(self, _pmd, _progtrack, _ignore_syncmd_nop,
+            _syncmd_tmp,
             accept=False,
-            li_attach_sync=False,
             li_md_only=False,
             li_pkg_updates=True,
             noexecute=False,
@@ -2718,9 +2839,6 @@
                 linked image metadata in the child and then possibly recursing
                 into the child to actually update packages.
 
-                'li_attach_sync' indicates if this sync is part of an attach
-                operation.
-
                 For descriptions of parameters please see the descriptions in
                 api.py`gen_plan_*"""
 
@@ -2732,8 +2850,7 @@
                         # we don't support updating packages in the parent
                         # during attach metadata only sync.
                         #
-                        assert not _pd
-                        if not self.__child_op_setup_syncmd(
+                        if not self.__child_op_setup_syncmd(_pmd,
                             ignore_syncmd_nop=False,
                             test=noexecute, stage=stage):
                                 # the update failed
@@ -2755,10 +2872,9 @@
                 # we don't support updating packages in the parent
                 # during attach.
                 #
-                assert not li_attach_sync or _pd is None
-                if not self.__child_op_setup_syncmd(
+                if not self.__child_op_setup_syncmd(_pmd,
                     ignore_syncmd_nop=_ignore_syncmd_nop,
-                    tmp=li_attach_sync, stage=stage, pd=_pd):
+                    tmp=_syncmd_tmp, stage=stage):
                         # the update failed or the metadata didn't change
                         return
 
@@ -2788,7 +2904,8 @@
                     update_index=update_index,
                     verbose=global_settings.client_output_verbose)
 
-        def __child_setup_update(self, _progtrack, _ignore_syncmd_nop, _pd,
+        def __child_setup_update(self, _pmd, _progtrack, _ignore_syncmd_nop,
+            _syncmd_tmp,
             accept=False,
             force=False,
             noexecute=False,
@@ -2800,8 +2917,9 @@
                 """Prepare to update a child image."""
 
                 # first sync the metadata
-                if not self.__child_op_setup_syncmd(
-                    ignore_syncmd_nop=_ignore_syncmd_nop, pd=_pd, stage=stage):
+                if not self.__child_op_setup_syncmd(_pmd,
+                    ignore_syncmd_nop=_ignore_syncmd_nop,
+                    tmp=_syncmd_tmp, stage=stage):
                         # the update failed or the metadata didn't change
                         return
 
@@ -2828,23 +2946,27 @@
                     update_index=update_index,
                     verbose=global_settings.client_output_verbose)
 
-        def __child_setup_detach(self, _progtrack, noexecute=False):
+        def __child_setup_detach(self, _progtrack, li_md_only=False,
+            li_pkg_updates=True, noexecute=False):
                 """Prepare to detach a child image."""
 
                 self.__pkg_remote.setup(self.child_path,
                     pkgdefs.PKG_OP_DETACH,
                     force=True,
+                    li_md_only=li_md_only,
+                    li_pkg_updates=li_pkg_updates,
                     li_target_all=False,
                     li_target_list=[],
                     noexecute=noexecute,
                     quiet=global_settings.client_output_quiet,
                     verbose=global_settings.client_output_verbose)
 
-        def __child_setup_pubcheck(self):
+        def __child_setup_pubcheck(self, _pmd):
                 """Prepare to a check if a child's publishers are in sync."""
 
                 # first sync the metadata
-                if not self.__child_op_setup_syncmd():
+                # a pubcheck should never update persistent meta data
+                if not self.__child_op_setup_syncmd(_pmd, tmp=True):
                         # the update failed
                         return
 
@@ -2852,12 +2974,12 @@
                 self.__pkg_remote.setup(self.child_path,
                     pkgdefs.PKG_OP_PUBCHECK)
 
-        def __child_setup_audit(self):
+        def __child_setup_audit(self, _pmd):
                 """Prepare to a child image to see if it's in sync with its
                 constraints."""
 
                 # first sync the metadata
-                if not self.__child_op_setup_syncmd():
+                if not self.__child_op_setup_syncmd(_pmd, tmp=True):
                         # the update failed
                         return
 
@@ -2876,25 +2998,25 @@
                 self.__pkg_remote.abort()
                 self.__child_op_rvtuple = None
 
-        def child_op_setup(self, _pkg_op, _progtrack, _ignore_syncmd_nop, _pd,
-            **kwargs):
+        def child_op_setup(self, _pkg_op, _pmd, _progtrack, _ignore_syncmd_nop,
+            _syncmd_tmp, **kwargs):
                 """Public interface to setup an operation that we'd like to
                 perform on a child image."""
 
                 assert self.__child_op_rvtuple is None
 
                 if _pkg_op == pkgdefs.PKG_OP_AUDIT_LINKED:
-                        self.__child_setup_audit(**kwargs)
+                        self.__child_setup_audit(_pmd, **kwargs)
                 elif _pkg_op == pkgdefs.PKG_OP_DETACH:
                         self.__child_setup_detach(_progtrack, **kwargs)
                 elif _pkg_op == pkgdefs.PKG_OP_PUBCHECK:
-                        self.__child_setup_pubcheck(**kwargs)
+                        self.__child_setup_pubcheck(_pmd, **kwargs)
                 elif _pkg_op == pkgdefs.PKG_OP_SYNC:
-                        self.__child_setup_sync(_progtrack,
-                            _ignore_syncmd_nop, _pd, **kwargs)
+                        self.__child_setup_sync(_pmd, _progtrack,
+                            _ignore_syncmd_nop, _syncmd_tmp, **kwargs)
                 elif _pkg_op == pkgdefs.PKG_OP_UPDATE:
-                        self.__child_setup_update(_progtrack,
-                            _ignore_syncmd_nop, _pd, **kwargs)
+                        self.__child_setup_update(_pmd, _progtrack,
+                            _ignore_syncmd_nop, _syncmd_tmp, **kwargs)
                 else:
                         raise RuntimeError(
                             "Unsupported package client op: %s" % _pkg_op)
@@ -3023,6 +3145,177 @@
 
 
 # ---------------------------------------------------------------------------
+# Interfaces to obtain linked image metadata from an image
+#
+def get_pubs(img):
+        """Return publisher information for the specified image.
+
+        Publisher information is returned in a sorted list of lists
+        of the format:
+                <publisher name>, <sticky>
+
+        Where:
+                <publisher name> is a string
+                <sticky> is a boolean
+
+        The tuples are sorted by publisher rank.
+        """
+
+        return [
+            [str(p), p.sticky]
+            for p in img.get_sorted_publishers(inc_disabled=False)
+        ]
+
+def get_packages(img, pd=None):
+        """Figure out the current (or planned) list of packages in img."""
+
+        ppkgs = set(img.get_catalog(img.IMG_CATALOG_INSTALLED).fmris())
+
+        # if there's an image plan the we need to update the installed
+        # packages based on that plan.
+        if pd is not None:
+                for src, dst in pd.plan_desc:
+                        if src == dst:
+                                continue
+                        if src:
+                                assert src in ppkgs
+                                ppkgs -= set([src])
+                        if dst:
+                                assert dst not in ppkgs
+                                ppkgs |= set([dst])
+
+        # paranoia
+        return frozenset(ppkgs)
+
+def get_inheritable_facets(img, pd=None):
+        """Get Facets from an image that a child should inherit.
+
+        We only want to sync facets which affect packages that have parent
+        dependencies on themselves.  In practice this essentially limits us to
+        "facet.version-lock.*" facets."""
+
+        # get installed (or planned) parent packages and facets
+        ppkgs = get_packages(img, pd=pd)
+        facets = img.cfg.facets
+        if pd is not None and pd.new_facets is not None:
+                facets = pd.new_facets
+
+        # create a packages dictionary indexed by package stem.
+        ppkgs_dict = dict([
+                (pfmri.pkg_name, pfmri)
+                for pfmri in ppkgs
+        ])
+
+        #
+        # iterate through all installed (or planned) package incorporation
+        # dependency actions and find those that are affected by image facets.
+        #
+        # we don't check for package-wide facets here because they don't do
+        # anything.  (ie, facets defined via "set" actions in a package have
+        # no effect on other actions within that package.)
+        #
+        faceted_deps = dict()
+        cat = img.get_catalog(img.IMG_CATALOG_KNOWN)
+        for pfmri in ppkgs:
+                for act in cat.get_entry_actions(pfmri, [cat.DEPENDENCY]):
+                        # we're only interested in incorporate dependencies
+                        if act.name != "depend" or \
+                            act.attrs["type"] != "incorporate":
+                                continue
+
+                        # check if any image facets affect this dependency
+                        # W0212 Access to a protected member
+                        # pylint: disable=W0212
+                        matching_facets = facets._action_match(act)
+                        # pylint: enable=W0212
+                        if not matching_facets:
+                                continue
+
+                        # if all the matching facets are true we don't care
+                        # about the match.
+                        if set([i[1] for i in matching_facets]) == set([True]):
+                                continue
+
+                        # save this set of facets.
+                        faceted_deps[act] = matching_facets
+
+        #
+        # For each faceted incorporation dependency, check if it affects a
+        # package that has parent dependencies on itself.  This is really a
+        # best effort in that we don't follow package renames or obsoletions,
+        # etc.
+        #
+        # To limit the number of packages we inspect, we'll try to match the
+        # incorporation dependency fmri targets packages by stem to packages
+        # which are installed (or planned) within the parent image.  This
+        # allows us to quickly get a fully qualified fmri and check against a
+        # package for which we have already downloaded a manifest.
+        #
+        # If we can't match the dependency fmri package stem against packages
+        # installed (or planned) in the parent image, we don't bother
+        # searching for allowable packages in the catalog, because even if we
+        # found them in the catalog and they did have a parent dependency,
+        # they'd all still be uninstallable in any children because there
+        # would be no way to satisfy the parent dependency.  (as we already
+        # stated the package is not installed in the parent.)
+        #
+        faceted_linked_deps = dict()
+        for act in faceted_deps:
+                for fmri in act.attrlist("fmri"):
+                        # the build_release specified below ("5.11") doesn't
+                        # matter since we only create a PkgFmri object so we
+                        # can reference pkg_name
+                        pfmri = pkg.fmri.PkgFmri(fmri, "5.11")
+                        pfmri = ppkgs_dict.get(pfmri.pkg_name, None)
+                        if pfmri is None:
+                                continue
+
+                        # check if this package has a dependency on itself in
+                        # its parent image.
+                        for act2 in cat.get_entry_actions(pfmri,
+                            [cat.DEPENDENCY]):
+                                if act2.name != "depend" or \
+                                    act2.attrs["type"] != "parent":
+                                        continue
+                                if pkg.actions.depend.DEPEND_SELF not in \
+                                    act2.attrlist("fmri"):
+                                        continue
+                                faceted_linked_deps[act] = faceted_deps[act]
+                                break
+        del faceted_deps
+
+        #
+        # Create a set of all facets which affect incorporation dependencies
+        # on synced packages.
+        #
+        # Note that we can't limit ourselves to only passing on facets that
+        # affect dependencies which have been disabled.  Doing this could lead
+        # to incorrect results because facets allow for pattern matching.  So
+        # for example say we had the following dependencies on synced
+        # packages:
+        #
+        #    depend type=incorporation fmri=some_synced_pkg1 facet.123456=true
+        #    depend type=incorporation fmri=some_synced_pkg2 facet.456789=true
+        #
+        # and the following image facets:
+        #
+        #    facet.123456 = True
+        #    facet.*456* = False
+        #
+        # if we only passed through facets which affected disabled packages
+        # we'd just pass through "facet.*456*", but this would result in
+        # disabling both dependencies above, not just the second dependency.
+        #
+        pfacets = pkg.facet.Facets()
+        for facets in faceted_linked_deps.values():
+                for k, v in facets:
+                        # W0212 Access to a protected member
+                        # pylint: disable=W0212
+                        pfacets._set_inherited(k, v)
+
+        return pfacets
+
+# ---------------------------------------------------------------------------
 # Utility Functions
 #
 def save_data(path, data, root="/"):
@@ -3051,12 +3344,12 @@
                 # pylint: disable=W0212
                 raise apx._convert_error(e)
 
-def load_data(path, missing_val=None):
+def load_data(path, missing_ok=False):
         """Load JSON encoded linked image metadata from a file."""
 
         try:
-                if (missing_val != None) and not path_exists(path):
-                        return missing_val
+                if missing_ok and not path_exists(path):
+                        return None
                 fobj = open(path)
                 data = json.load(fobj, encoding="utf-8",
                     object_hook=pkg.client.linkedimage.PkgDecoder)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/client/options.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,843 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+
+import os
+
+import pkg.client.pkgdefs as pkgdefs
+import pkg.client.linkedimage as li
+import pkg.misc as misc
+
+from pkg.client.api_errors import InvalidOptionError
+from pkg.client import global_settings
+
+_orig_cwd = None
+
+# List of available options for common option processing.
+ACCEPT                = "accept"
+ALLOW_RELINK          = "allow_relink"
+ATTACH_CHILD          = "attach_child"
+ATTACH_PARENT         = "attach_parent"
+BACKUP_BE             = "backup_be"
+BACKUP_BE_NAME        = "backup_be_name"
+BE_ACTIVATE           = "be_activate"
+BE_NAME               = "be_name"
+CONCURRENCY           = "concurrency"
+DENY_NEW_BE           = "deny_new_be"
+FORCE                 = "force"
+LI_IGNORE             = "li_ignore"
+LI_IGNORE_ALL         = "li_ignore_all"
+LI_IGNORE_LIST        = "li_ignore_list"
+LI_MD_ONLY            = "li_md_only"
+LI_NAME               = "li_name"
+LI_PARENT_SYNC        = "li_parent_sync"
+LI_PKG_UPDATES        = "li_pkg_updates"
+LI_PROPS              = "li_props"
+LI_TARGET_ALL         = "li_target_all"
+LI_TARGET_LIST        = "li_target_list"
+LIST_ALL              = "list_all"
+LIST_INSTALLED_NEWEST = "list_installed_newest"
+LIST_NEWEST           = "list_newest"
+LIST_UPGRADABLE       = "list_upgradable"
+MED_IMPLEMENTATION    = "med_implementation"
+MED_VERSION           = "med_version"
+NEW_BE                = "new_be"
+NO_BACKUP_BE          = "no_backup_be"
+NOEXECUTE             = "noexecute"
+OMIT_HEADERS          = "omit_headers"
+ORIGINS               = "origins"
+PARSABLE_VERSION      = "parsable_version"
+QUIET                 = "quiet"
+REFRESH_CATALOGS      = "refresh_catalogs"
+REJECT_PATS           = "reject_pats"
+REQUIRE_BACKUP_BE     = "require_backup_be"
+REQUIRE_NEW_BE        = "require_new_be"
+SHOW_LICENSES         = "show_licenses"
+STAGE                 = "stage"
+SUMMARY               = "summary"
+TAGGED                = "tagged"
+UPDATE_INDEX          = "update_index"
+VERBOSE               = "verbose"
+
+
+
+def opts_table_cb_beopts(api_inst, opts, opts_new):
+
+        # synthesize require_new_be and deny_new_be into new_be
+        del opts_new[REQUIRE_NEW_BE]
+        del opts_new[DENY_NEW_BE]
+        opts_new[NEW_BE] = None
+
+        if (opts[BE_NAME] or opts[REQUIRE_NEW_BE]) and opts[DENY_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [REQUIRE_NEW_BE, DENY_NEW_BE])
+
+        # create a new key called BACKUP_BE in the options array
+        if opts[REQUIRE_NEW_BE] or opts[BE_NAME]:
+                opts_new[NEW_BE] = True
+        if opts[DENY_NEW_BE]:
+                opts_new[NEW_BE] = False
+
+        # synthesize require_backup_be and no_backup_be into backup_be
+        del opts_new[REQUIRE_BACKUP_BE]
+        del opts_new[NO_BACKUP_BE]
+        opts_new[BACKUP_BE] = None
+
+        if (opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]) and \
+            opts[NO_BACKUP_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [REQUIRE_BACKUP_BE, NO_BACKUP_BE])
+
+        if (opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]) and \
+            (opts[REQUIRE_NEW_BE] or opts[BE_NAME]):
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [REQUIRE_BACKUP_BE, REQUIRE_NEW_BE])
+
+        # create a new key called BACKUP_BE in the options array
+        if opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]:
+                opts_new[BACKUP_BE] = True
+        if opts[NO_BACKUP_BE]:
+                opts_new[BACKUP_BE] = False
+
+def opts_table_cb_li_ignore(api_inst, opts, opts_new):
+
+        # synthesize li_ignore_all and li_ignore_list into li_ignore
+        del opts_new[LI_IGNORE_ALL]
+        del opts_new[LI_IGNORE_LIST]
+        opts_new[LI_IGNORE] = None
+
+        # check if there's nothing to ignore
+        if not opts[LI_IGNORE_ALL] and not opts[LI_IGNORE_LIST]:
+                return
+
+        if opts[LI_IGNORE_ALL]:
+
+                # can't ignore all and specific images
+                if opts[LI_IGNORE_LIST]:
+                        raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                            [LI_IGNORE_ALL, LI_IGNORE_LIST])
+
+                # can't ignore all and target anything.
+                if LI_TARGET_ALL in opts and opts[LI_TARGET_ALL]:
+                        raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                            [LI_IGNORE_ALL, LI_TARGET_ALL])
+                if LI_TARGET_LIST in opts and opts[LI_TARGET_LIST]:
+                        raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                            [LI_IGNORE_ALL, LI_TARGET_LIST])
+                if LI_NAME in opts and opts[LI_NAME]:
+                        raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                            [LI_IGNORE_ALL, LI_NAME])
+                opts_new[LI_IGNORE] = []
+                return
+
+        assert opts[LI_IGNORE_LIST]
+
+        # it doesn't make sense to specify images to ignore if the
+        # user is already specifying images to operate on.
+        if LI_TARGET_ALL in opts and opts[LI_TARGET_ALL]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LI_IGNORE_LIST, LI_TARGET_ALL])
+        if LI_TARGET_LIST in opts and opts[LI_TARGET_LIST]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LI_IGNORE_LIST, LI_TARGET_LIST])
+        if LI_NAME in opts and opts[LI_NAME]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LI_IGNORE_LIST, LI_NAME])
+
+        li_ignore = []
+        for li_name in opts[LI_IGNORE_LIST]:
+                # check for repeats
+                if li_name in li_ignore:
+                        raise InvalidOptionError(
+                            InvalidOptionError.ARG_REPEAT, [li_name,
+                            LI_IGNORE_LIST])
+                # add to ignore list
+                li_ignore.append(li_name)
+
+        opts_new[LI_IGNORE] = api_inst.parse_linked_name_list(li_ignore)
+
+def opts_table_cb_li_no_psync(api_inst, opts, opts_new):
+        # if a target child linked image was specified, the no-parent-sync
+        # option doesn't make sense since we know that both the parent and
+        # child image are accessible
+
+        if LI_TARGET_ALL not in opts:
+                # we don't accept linked image target options
+                assert LI_TARGET_LIST not in opts
+                return
+
+        if opts[LI_TARGET_ALL] and not opts[LI_PARENT_SYNC]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [LI_TARGET_ALL, LI_PARENT_SYNC])
+
+        if opts[LI_TARGET_LIST] and not opts[LI_PARENT_SYNC]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [LI_TARGET_LIST, LI_PARENT_SYNC])
+
+
+def __parse_linked_props(args):
+        """"Parse linked image property options that were specified on the
+        command line into a dictionary.  Make sure duplicate properties were
+        not specified."""
+
+        linked_props = dict()
+        for pv in args:
+                try:
+                        p, v = pv.split("=", 1)
+                except ValueError:
+                        raise InvalidOptionError(msg=_("linked image "
+                            "property arguments must be of the form "
+                            "'<name>=<value>'."))
+
+                if p not in li.prop_values:
+                        raise InvalidOptionError(msg=_("invalid linked "
+                        "image property: '%s'.") % p)
+
+                if p in linked_props:
+                        raise InvalidOptionError(msg=_("linked image "
+                            "property specified multiple times: '%s'.") % p)
+
+                linked_props[p] = v
+
+        return linked_props
+
+def opts_table_cb_li_props(api_inst, opts, opts_new):
+        """convert linked image prop list into a dictionary"""
+
+        opts_new[LI_PROPS] = __parse_linked_props(opts[LI_PROPS])
+
+def opts_table_cb_li_target(api_inst, opts, opts_new):
+        # figure out which option the user specified
+        if opts[LI_TARGET_ALL] and opts[LI_TARGET_LIST]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LI_TARGET_ALL, LI_TARGET_LIST])
+        elif opts[LI_TARGET_ALL]:
+                arg1 = LI_TARGET_ALL
+        elif opts[LI_TARGET_LIST]:
+                arg1 = LI_TARGET_LIST
+        else:
+                return
+
+        if BE_ACTIVATE in opts and not opts[BE_ACTIVATE]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [arg1, BE_ACTIVATE])
+        if BE_NAME in opts and opts[BE_NAME]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, BE_NAME])
+        if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, DENY_NEW_BE])
+        if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REQUIRE_NEW_BE])
+        if REJECT_PATS in opts and opts[REJECT_PATS]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REJECT_PATS])
+        if ORIGINS in opts and opts[ORIGINS]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, ORIGINS])
+
+        # validate linked image name
+        li_target_list = []
+        for li_name in opts[LI_TARGET_LIST]:
+                # check for repeats
+                if li_name in li_target_list:
+                        raise InvalidOptionError(
+                            InvalidOptionError.ARG_REPEAT, [li_name,
+                            LI_TARGET_LIST])
+                # add to ignore list
+                li_target_list.append(li_name)
+
+        opts_new[LI_TARGET_LIST] = \
+            api_inst.parse_linked_name_list(li_target_list)
+
+def opts_table_cb_li_target1(api_inst, opts, opts_new):
+        # figure out which option the user specified
+        if opts[LI_NAME]:
+                arg1 = LI_NAME
+        else:
+                return
+
+        if BE_ACTIVATE in opts and not opts[BE_ACTIVATE]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [arg1, BE_ACTIVATE])
+        if BE_NAME in opts and opts[BE_NAME]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, BE_NAME])
+        if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, DENY_NEW_BE])
+        if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REQUIRE_NEW_BE])
+        if REJECT_PATS in opts and opts[REJECT_PATS]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REJECT_PATS])
+        if ORIGINS in opts and opts[ORIGINS]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, ORIGINS])
+
+def opts_table_cb_no_headers_vs_quiet(api_inst, opts, opts_new):
+        # check if we accept the -q option
+        if QUIET not in opts:
+                return
+
+        # -q implies -H
+        if opts[QUIET]:
+                opts_new[OMIT_HEADERS] = True
+
+def opts_table_cb_q(api_inst, opts, opts_new):
+        # Be careful not to overwrite global_settings.client_output_quiet
+        # because it might be set "True" from elsewhere, e.g. in
+        # opts_table_cb_parsable.
+        if opts[QUIET] is True:
+                global_settings.client_output_quiet = True
+
+def opts_table_cb_v(api_inst, opts, opts_new):
+        global_settings.client_output_verbose = opts[VERBOSE]
+
+def opts_table_cb_nqv(api_inst, opts, opts_new):
+        if opts[VERBOSE] and opts[QUIET]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [VERBOSE, QUIET])
+
+def opts_table_cb_parsable(api_inst, opts, opts_new):
+        if opts[PARSABLE_VERSION] and opts.get(VERBOSE, False):
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [VERBOSE, PARSABLE_VERSION])
+        if opts[PARSABLE_VERSION]:
+                try:
+                        opts_new[PARSABLE_VERSION] = int(
+                            opts[PARSABLE_VERSION])
+                except ValueError:
+                        raise InvalidOptionError(
+                            options=[PARSABLE_VERSION],
+                            msg=_("integer argument expected"))
+
+                global_settings.client_output_parsable_version = \
+                    opts_new[PARSABLE_VERSION]
+                opts_new[QUIET] = True
+                global_settings.client_output_quiet = True
+
+def opts_table_cb_origins(api_inst, opts, opts_new):
+        origins = set()
+        for o in opts[ORIGINS]:
+                origins.add(misc.parse_uri(o, cwd=_orig_cwd))
+        opts_new[ORIGINS] = origins
+
+def opts_table_cb_stage(api_inst, opts, opts_new):
+        if opts[STAGE] == None:
+                opts_new[STAGE] = pkgdefs.API_STAGE_DEFAULT
+                return
+
+        if opts_new[STAGE] not in pkgdefs.api_stage_values:
+                raise InvalidOptionError(msg=_("invalid operation stage: "
+                    "'%s'") % opts[STAGE])
+
+def opts_cb_li_attach(api_inst, opts, opts_new):
+        if opts[ATTACH_PARENT] and opts[ATTACH_CHILD]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [ATTACH_PARENT, ATTACH_CHILD])
+
+        if not opts[ATTACH_PARENT] and not opts[ATTACH_CHILD]:
+                raise InvalidOptionError(InvalidOptionError.XOR,
+                    [ATTACH_PARENT, ATTACH_CHILD])
+
+        if opts[ATTACH_CHILD]:
+                # if we're attaching a new child then that doesn't affect
+                # any other children, so ignoring them doesn't make sense.
+                if opts[LI_IGNORE_ALL]:
+                        raise InvalidOptionError(
+                            InvalidOptionError.INCOMPAT,
+                            [ATTACH_CHILD, LI_IGNORE_ALL])
+                if opts[LI_IGNORE_LIST]:
+                        raise InvalidOptionError(
+                            InvalidOptionError.INCOMPAT,
+                            [ATTACH_CHILD, LI_IGNORE_LIST])
+
+def opts_table_cb_md_only(api_inst, opts, opts_new):
+        # if the user didn't specify linked-md-only we're done
+        if not opts[LI_MD_ONLY]:
+                return
+
+        # li_md_only implies no li_pkg_updates
+        if LI_PKG_UPDATES in opts:
+                opts_new[LI_PKG_UPDATES] = False
+
+        #
+        # if li_md_only is false that means we're not updating any packages
+        # within the current image so there are a ton of options that no
+        # longer apply to the current operation, and hence are incompatible
+        # with li_md_only.
+        #
+        arg1 = LI_MD_ONLY
+        if BE_NAME in opts and opts[BE_NAME]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, BE_NAME])
+        if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, DENY_NEW_BE])
+        if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REQUIRE_NEW_BE])
+        if LI_PARENT_SYNC in opts and not opts[LI_PARENT_SYNC]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [arg1, LI_PARENT_SYNC])
+        if REJECT_PATS in opts and opts[REJECT_PATS]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [arg1, REJECT_PATS])
+
+def opts_cb_list(api_inst, opts, opts_new):
+        if opts_new[ORIGINS] and opts_new[LIST_UPGRADABLE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [ORIGINS, LIST_UPGRADABLE])
+
+        if opts_new[ORIGINS] and not opts_new[LIST_NEWEST]:
+                # Use of -g implies -a unless -n is provided.
+                opts_new[LIST_INSTALLED_NEWEST] = True
+
+        if opts_new[LIST_ALL] and not opts_new[LIST_INSTALLED_NEWEST]:
+                raise InvalidOptionError(InvalidOptionError.REQUIRED,
+                    [LIST_ALL, LIST_INSTALLED_NEWEST])
+
+        if opts_new[LIST_INSTALLED_NEWEST] and opts_new[LIST_NEWEST]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LIST_INSTALLED_NEWEST, LIST_NEWEST])
+
+        if opts_new[LIST_INSTALLED_NEWEST] and opts_new[LIST_UPGRADABLE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [LIST_INSTALLED_NEWEST, LIST_UPGRADABLE])
+
+        if opts_new[SUMMARY] and opts_new[VERBOSE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [SUMMARY, VERBOSE])
+
+        if opts_new[QUIET] and opts_new[VERBOSE]:
+                raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+                    [QUIET, VERBOSE])
+
+def opts_cb_int(k, api_inst, opts, opts_new, minimum=None):
+
+        if k not in opts or opts[k] == None:
+                err = _("missing required parameter")
+                raise InvalidOptionError(msg=err, options=[k])
+
+        # get the original argument value
+        v = opts[k]
+
+        # make sure it is an integer
+        try:
+                v = int(v)
+        except (ValueError, TypeError):
+                # not a valid integer
+                err = _("value '%s' invalid") % (v)
+                raise InvalidOptionError(msg=err, options=[k])
+
+        # check the minimum bounds
+        if minimum is not None and v < minimum:
+                err = _("value must be >= %d") % (minimum)
+                raise InvalidOptionError(msg=err, options=[k])
+
+        # update the new options array to make the value an integer
+        opts_new[k] = v
+
+def opts_cb_fd(k, api_inst, opts, opts_new):
+        opts_cb_int(k, api_inst, opts, opts_new, minimum=0)
+
+        err = _("value '%s' invalid") % (opts_new[k])
+        try:
+                os.fstat(opts_new[k])
+        except OSError:
+                # not a valid file descriptor
+                raise InvalidOptionError(msg=err, options=[k])
+
+def opts_table_cb_concurrency(api_inst, opts, opts_new):
+        if opts[CONCURRENCY] is None:
+                # remove concurrency from parameters dict
+                del opts_new[CONCURRENCY]
+                return
+
+        # make sure we have an integer
+        opts_cb_int(CONCURRENCY, api_inst, opts, opts_new)
+
+        # update global concurrency setting
+        global_settings.client_concurrency = opts_new[CONCURRENCY]
+        global_settings.client_concurrency_set = True
+
+        # remove concurrency from parameters dict
+        del opts_new[CONCURRENCY]
+
+#
+# options common to multiple pkg(1) operations.  The format for specifying
+# options is a list which can contain:
+#
+# - Tuples formatted as:
+#       (k, v)
+#   where the values are:
+#       k: the key value for the options dictionary
+#       v: the default value. valid values are: True/False, None, [], 0
+#
+
+
+opts_table_beopts = [
+    opts_table_cb_beopts,
+    (BACKUP_BE_NAME,     None),
+    (BE_NAME,            None),
+    (DENY_NEW_BE,        False),
+    (NO_BACKUP_BE,       False),
+    (BE_ACTIVATE,        True),
+    (REQUIRE_BACKUP_BE,  False),
+    (REQUIRE_NEW_BE,     False),
+]
+
+opts_table_concurrency = [
+    opts_table_cb_concurrency,
+    (CONCURRENCY,        None),
+]
+
+opts_table_force = [
+    (FORCE,                False),
+]
+
+opts_table_li_ignore = [
+    opts_table_cb_li_ignore,
+    (LI_IGNORE_ALL,        False),
+    (LI_IGNORE_LIST,       []),
+]
+
+opts_table_li_md_only = [
+    opts_table_cb_md_only,
+    (LI_MD_ONLY,         False),
+]
+
+opts_table_li_no_pkg_updates = [
+    (LI_PKG_UPDATES,       True),
+]
+
+opts_table_li_no_psync = [
+    opts_table_cb_li_no_psync,
+    (LI_PARENT_SYNC,       True),
+]
+
+opts_table_li_props = [
+    opts_table_cb_li_props,
+    (LI_PROPS,             []),
+]
+
+opts_table_li_target = [
+    opts_table_cb_li_target,
+    (LI_TARGET_ALL,        False),
+    (LI_TARGET_LIST,       []),
+]
+
+opts_table_li_target1 = [
+    opts_table_cb_li_target1,
+    (LI_NAME,              None),
+]
+
+opts_table_licenses = [
+    (ACCEPT,               False),
+    (SHOW_LICENSES,        False),
+]
+
+opts_table_no_headers = [
+    opts_table_cb_no_headers_vs_quiet,
+    (OMIT_HEADERS,         False),
+]
+
+opts_table_no_index = [
+    (UPDATE_INDEX,         True),
+]
+
+opts_table_no_refresh = [
+    (REFRESH_CATALOGS,     True),
+]
+
+opts_table_reject = [
+    (REJECT_PATS,          []),
+]
+
+opts_table_verbose = [
+    opts_table_cb_v,
+    (VERBOSE,              0),
+]
+
+opts_table_quiet = [
+    opts_table_cb_q,
+    (QUIET,                False),
+]
+
+opts_table_parsable = [
+    opts_table_cb_parsable,
+    (PARSABLE_VERSION,     None),
+]
+
+opts_table_nqv = \
+    opts_table_quiet + \
+    opts_table_verbose + \
+    [
+    opts_table_cb_nqv,
+    (NOEXECUTE,            False),
+]
+
+opts_table_origins = [
+    opts_table_cb_origins,
+    (ORIGINS,              []),
+]
+
+opts_table_stage = [
+    opts_table_cb_stage,
+    (STAGE,                None),
+]
+
+#
+# Options for pkg(1) subcommands.  Built by combining the option tables above,
+# with some optional subcommand unique options defined below.
+#
+opts_install = \
+    opts_table_beopts + \
+    opts_table_concurrency + \
+    opts_table_li_ignore + \
+    opts_table_li_no_psync + \
+    opts_table_licenses + \
+    opts_table_reject + \
+    opts_table_no_index + \
+    opts_table_no_refresh + \
+    opts_table_nqv + \
+    opts_table_parsable + \
+    opts_table_origins + \
+    []
+
+# "update" cmd inherits all "install" cmd options
+opts_update = \
+    opts_install + \
+    opts_table_force + \
+    opts_table_stage + \
+    []
+
+# "attach-linked" cmd inherits all "install" cmd options
+opts_attach_linked = \
+    opts_install + \
+    opts_table_force + \
+    opts_table_li_md_only + \
+    opts_table_li_no_pkg_updates + \
+    opts_table_li_props + \
+    [
+    opts_cb_li_attach,
+    (ALLOW_RELINK,         False),
+    (ATTACH_CHILD,         False),
+    (ATTACH_PARENT,        False),
+]
+
+opts_revert = \
+    opts_table_beopts + \
+    opts_table_nqv + \
+    opts_table_parsable + \
+    [
+    (TAGGED,               False),
+]
+
+opts_set_mediator = \
+    opts_table_beopts + \
+    opts_table_no_index + \
+    opts_table_nqv + \
+    opts_table_parsable + \
+    [
+    (MED_IMPLEMENTATION,   None),
+    (MED_VERSION,          None)
+]
+
+# "set-property-linked" cmd inherits all "install" cmd options
+opts_set_property_linked = \
+    opts_install + \
+    opts_table_li_md_only + \
+    opts_table_li_no_pkg_updates + \
+    opts_table_li_target1 + \
+    []
+
+# "sync-linked" cmd inherits all "install" cmd options
+opts_sync_linked = \
+    opts_install + \
+    opts_table_li_md_only + \
+    opts_table_li_no_pkg_updates + \
+    opts_table_li_target + \
+    opts_table_stage + \
+    []
+
+opts_uninstall = \
+    opts_table_beopts + \
+    opts_table_concurrency + \
+    opts_table_li_ignore + \
+    opts_table_li_no_psync + \
+    opts_table_no_index + \
+    opts_table_nqv + \
+    opts_table_parsable + \
+    opts_table_stage
+
+opts_audit_linked = \
+    opts_table_li_no_psync + \
+    opts_table_li_target + \
+    opts_table_no_headers + \
+    opts_table_quiet + \
+    []
+
+opts_detach_linked = \
+    opts_table_force + \
+    opts_table_li_md_only + \
+    opts_table_li_no_pkg_updates + \
+    opts_table_li_target + \
+    opts_table_nqv + \
+    []
+
+opts_list_linked = \
+    opts_table_li_ignore + \
+    opts_table_no_headers + \
+    []
+
+opts_list_property_linked = \
+    opts_table_li_target1 + \
+    opts_table_no_headers + \
+    []
+
+opts_list_inventory = \
+    opts_table_li_no_psync + \
+    opts_table_no_refresh + \
+    opts_table_no_headers + \
+    opts_table_origins + \
+    opts_table_quiet + \
+    opts_table_verbose + \
+    [
+    opts_cb_list,
+    (LIST_INSTALLED_NEWEST, False),
+    (LIST_ALL,              False),
+    (LIST_NEWEST,           False),
+    (SUMMARY,               False),
+    (LIST_UPGRADABLE,       False),
+]
+
+pkg_op_opts = {
+
+    pkgdefs.PKG_OP_ATTACH         : opts_attach_linked,
+    pkgdefs.PKG_OP_AUDIT_LINKED   : opts_audit_linked,
+    pkgdefs.PKG_OP_CHANGE_FACET   : opts_install,
+    pkgdefs.PKG_OP_CHANGE_VARIANT : opts_install,
+    pkgdefs.PKG_OP_DETACH         : opts_detach_linked,
+    pkgdefs.PKG_OP_INSTALL        : opts_install,
+    pkgdefs.PKG_OP_LIST           : opts_list_inventory,
+    pkgdefs.PKG_OP_LIST_LINKED    : opts_list_linked,
+    pkgdefs.PKG_OP_PROP_LINKED    : opts_list_property_linked,
+    pkgdefs.PKG_OP_PUBCHECK       : [],
+    pkgdefs.PKG_OP_REVERT         : opts_revert,
+    pkgdefs.PKG_OP_SET_MEDIATOR   : opts_set_mediator,
+    pkgdefs.PKG_OP_SET_PROP_LINKED: opts_set_property_linked,
+    pkgdefs.PKG_OP_SYNC           : opts_sync_linked,
+    pkgdefs.PKG_OP_UNINSTALL      : opts_uninstall,
+    pkgdefs.PKG_OP_UPDATE         : opts_update
+}
+
+def get_pkg_opts(op, add_table=None):
+        """Get the available options for a particular operation specified by
+        'op'. If the client uses custom pkg_op_opts tables they can be specified
+        by 'add_table'."""
+
+        popts = pkg_op_opts.copy()
+        if add_table is not None:
+                popts.update(add_table)
+
+        try:
+                opts = popts[op]
+        except KeyError:
+                opts = None
+        return opts
+
+def get_pkg_opts_defaults(op, opt, add_table=None):
+        """ Get the default value for a certain option 'opt' of a certain
+        operation 'op'. This is useful for clients which toggle boolean options.
+        """
+        popts = get_pkg_opts(op, add_table)
+
+        for o in popts:
+                if type(o) != tuple:
+                        continue
+                opt_name, default = o
+                if opt_name == opt:
+                        return default
+
+def opts_assemble(op, api_inst, opts, add_table=None, cwd=None):
+        """Assembly of the options for a specific operation. Options are read in
+        from a dict (see explanation below) and sanity tested.
+
+        This is the common interface to supply options to the functions of the
+        API.
+
+        'op' is the operation for which the options need to be assembled and
+        verified. The currently supported operations are listed in
+        pkgdefs.pkg_op_values.
+
+        'api_inst' is a reference to the API instance, required for some of the
+        verification steps.
+
+        'opts' is the raw options table to be processed. It needs to be a dict
+        in the format: { option_name: argument, ... }
+        """
+
+        global _orig_cwd
+
+        if cwd is not None:
+                _orig_cwd = cwd
+        else:
+                _orig_cwd = None
+
+        popts = get_pkg_opts(op, add_table)
+
+        rv = {}
+        callbacks = []
+
+        for o in popts:
+                if type(o) != tuple:
+                        callbacks.append(o)
+                        continue
+
+                avail_opt, default = o
+                # for options not given we substitue the default value
+                if avail_opt not in opts:
+                        rv[avail_opt] = default
+                        continue
+
+                if type(default) == int:
+                        assert type(opts[avail_opt]) == int, opts[avail_opt]
+                elif type(default) == list:
+                        assert type(opts[avail_opt]) == list, opts[avail_opt]
+                elif type(default) == bool:
+                        assert type(opts[avail_opt]) == bool, opts[avail_opt]
+
+                rv[avail_opt] = opts[avail_opt]
+
+        rv_updated = rv.copy()
+
+        # run the option verification callbacks
+        for cb in callbacks:
+                cb(api_inst, rv, rv_updated)
+
+        return rv_updated
+
--- a/src/modules/client/pkg_solver.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/pkg_solver.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,14 +21,15 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
-
+import os
 import time
 
 import pkg.actions
 import pkg.catalog           as catalog
 import pkg.client.api_errors as api_errors
+
 import pkg.client.image
 import pkg.fmri
 import pkg.misc as misc
@@ -38,6 +39,7 @@
 from collections import defaultdict
 from itertools import chain
 from pkg.client.debugvalues import DebugValues
+from pkg.client.firmware import Firmware
 from pkg.misc import EmptyI, EmptyDict, N_
 
 SOLVER_INIT    = "Initialized"
@@ -153,6 +155,9 @@
                             for f in self.__parent_pkgs
                         ])
 
+		# cache of firmware dependencies
+		self.__firmware = Firmware()
+
         def __str__(self):
 
                 s = "Solver: ["
@@ -205,6 +210,7 @@
                 self.__start_time = None
                 self.__dependents = None
                 self.__fmridict = {}
+		self.__firmware = None
 
                 if DebugValues["plan"]:
                         # Remaining data must be kept.
@@ -355,7 +361,9 @@
                 if relax_all:
                         relax_pkgs = self.__installed_pkgs
                 else:
-                        relax_pkgs = proposed_pkgs
+                        relax_pkgs = proposed_pkgs | \
+                            self.__relax_parent_self_constrained(excludes,
+                                ignore_inst_parent_deps)
 
                 inc_list, con_lists = self.__get_installed_unbound_inc_list(
                     relax_pkgs, excludes=excludes)
@@ -1629,6 +1637,35 @@
                             (dtype, fmri)),
                             matching)
 
+        def __relax_parent_self_constrained(self, excludes, \
+            ignore_inst_parent_deps):
+                """If we're a child image then we need to relax packages
+                that are dependent upon themselves in the parent image.  This
+                is necessary to keep those packages in sync."""
+
+                relax_pkgs = set()
+
+                # check if we're a child image.
+                if self.__parent_pkgs is None:
+                        return relax_pkgs
+
+                # if we're ignoring parent dependencies there is no reason to
+                # relax install-holds in packages constrained by those
+                # dependencies.
+                if ignore_inst_parent_deps:
+                        return relax_pkgs
+
+                for f in self.__installed_fmris:
+                        for da in self.__get_dependency_actions(f, excludes):
+                                if da.attrs["type"] != "parent":
+                                        continue
+                                if pkg.actions.depend.DEPEND_SELF in \
+                                    da.attrlist("fmri"):
+                                        relax_pkgs.add(f.pkg_name)
+                                        break
+
+                return relax_pkgs
+
         def __generate_dependency_errors(self, fmri_list, excludes=EmptyI):
                 """ Returns a list of strings describing why fmris cannot
                 be installed, or returns an empty list if installation
@@ -1711,7 +1748,10 @@
                 tag = _("Reason:")
 
                 if fmri in already_seen:
-                        reason = _("%s  %s  [already rejected; see above]") % (indent, tag)
+                        # note to translators: 'indent' will be a series of
+                        # whitespaces.
+                        reason = _("%(indent)s  %(tag)s  [already rejected; "
+                            "see above]") % {"indent": indent, "tag": tag}
                         return fmri_id, [reason]
 
                 already_seen.add(fmri)
@@ -2069,16 +2109,24 @@
 
                 if fmri.pkg_name not in self.__parent_dict:
                         # package is not installed in parent
-                        reason = (N_("Package is not installed in "
-                            "parent image: {0}"), (fmri.pkg_name,))
+                        if self.__is_zone():
+                                reason = (N_("Package {0} is not installed in "
+                                    "global zone."), (fmri.pkg_name,))
+                        else:
+                                reason = (N_("Package {0} is not installed in "
+                                    "parent image."), (fmri.pkg_name,))
                         self.__trim(pkg_fmri, reason)
                         return False
 
                 pf = self.__parent_dict[fmri.pkg_name]
                 if fmri.publisher and fmri.publisher != pf.publisher:
                         # package is from a different publisher in the parent
-                        reason = (N_("Package in parent is from a "
-                            "different publisher: {0}"), (pf,))
+                        if self.__is_zone():
+                                reason = (N_("Package in global zone is from "
+                                    "a different publisher: {0}"), (pf,))
+                        else:
+                                reason = (N_("Package in parent is from a "
+                                    "different publisher: {0}"), (pf,))
                         self.__trim(pkg_fmri, reason)
                         return False
 
@@ -2090,11 +2138,19 @@
                 # version mismatch
                 if pf.version.is_successor(fmri.version,
                     version.CONSTRAINT_NONE):
-                        reason = (N_("Parent image has a incompatible newer "
-                            "version: {0}"), (pf,))
+                        if self.__is_zone():
+                                reason = (N_("Global zone has a "
+                                    "newer version: {0}"), (pf,))
+                        else:
+                                reason = (N_("Parent image has a "
+                                    "newer version: {0}"), (pf,))
                 else:
-                        reason = (N_("Parent image has an older version of "
-                            "package: {0}"), (pf,))
+                        if self.__is_zone():
+                                reason = (N_("Global zone has an older "
+                                    "version of package: {0}"), (pf,))
+                        else:
+                                reason = (N_("Parent image has an older "
+                                    "version of package: {0}"), (pf,))
 
                 self.__trim(pkg_fmri, reason)
                 return False
@@ -2152,22 +2208,32 @@
                         req_fmri = pkg.fmri.PkgFmri(da.attrs["fmri"], "5.11")
 
                         if da.attrs.get("root-image", "").lower() == "true":
-                                if self.__root_fmris is None:
-                                        img = pkg.client.image.Image(
-                                            misc.liveroot(),
-                                            allow_ondisk_upgrade=False,
-                                            user_provided_dir=True,
-                                            should_exist=True)
-                                        self.__root_fmris = dict([
-                                            (f.pkg_name, f)
-                                            for f in img.gen_installed_pkgs()
-                                        ])
+				if req_fmri.pkg_name.startswith("feature/firmware/"):
+					# this is a firmware dependency
+					fw_ok, reason = \
+					    self.__firmware.check_firmware(da,
+					    req_fmri.pkg_name)
+					if not fw_ok:
+						self.__trim(fmri, reason)
+						return False
+					continue
+				else:
+					if self.__root_fmris is None:
+						img = pkg.client.image.Image(
+						    misc.liveroot(),
+						    allow_ondisk_upgrade=False,
+						    user_provided_dir=True,
+						    should_exist=True)
+						self.__root_fmris = dict([
+						    (f.pkg_name, f)
+						    for f in img.gen_installed_pkgs()
+						])
 
-                                installed = self.__root_fmris.get(
-                                    req_fmri.pkg_name, None)
-                                reason = (N_("Installed version in root image "
-                                    "is too old for origin dependency {0}"),
-                                    (req_fmri,))
+					installed = self.__root_fmris.get(
+					    req_fmri.pkg_name, None)
+					reason = (N_("Installed version in root image "
+					    "is too old for origin dependency {0}"),
+					    (req_fmri,))
                         else:
                                 installed = self.__installed_dict.get(
                                     req_fmri.pkg_name, None)
@@ -2200,3 +2266,11 @@
                         if f not in self.__trim_dict
                         ]
                 return ret
+
+        def __is_zone(self):
+                """Return True if image is a nonglobal zone"""
+                if 'variant.opensolaris.zone' in self.__variants:
+                        return self.__variants['variant.opensolaris.zone'] == \
+                            'nonglobal'
+                else:
+                        return False
--- a/src/modules/client/pkgremote.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/pkgremote.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """
@@ -210,7 +210,9 @@
                 """Drain the client progress pipe."""
 
                 progfd = self.__rpc_client_prog_pipe_fobj.fileno()
-                while select.select([progfd], [], [], 0)[0]:
+                p = select.poll()
+                p.register(progfd, select.POLLIN)
+                while p.poll(0):
                         os.read(progfd, 10240)
 
         def __state_verify(self, state=None):
--- a/src/modules/client/plandesc.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/plandesc.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """
@@ -112,17 +112,16 @@
                     "implementation-version": pkg.version.Version,
                 }
             },
-            "_changed_facets": pkg.facet.Facets,
             "_fmri_changes": [ ( pkg.fmri.PkgFmri, pkg.fmri.PkgFmri ) ],
             "_new_avoid_obs": ( set(), set() ),
-            "_new_facets": pkg.facet.Facets,
             "_new_mediators": collections.defaultdict(set, {
                 str: {
                     "version": pkg.version.Version,
                     "implementation-version": pkg.version.Version,
                 }
             }),
-            "_removed_facets": set(),
+            "_old_facets": pkg.facet.Facets,
+            "_new_facets": pkg.facet.Facets,
             "_rm_aliases": { str: set() },
             "added_groups": { str: pkg.fmri.PkgFmri },
             "added_users": { str: pkg.fmri.PkgFmri },
@@ -130,6 +129,7 @@
             "children_nop": [ li.LinkedImageName ],
             "children_planned": [ li.LinkedImageName ],
             "install_actions": [ _ActionPlan ],
+            "li_pfacets": pkg.facet.Facets,
             "li_ppkgs": frozenset([ pkg.fmri.PkgFmri ]),
             "li_props": { li.PROP_NAME: li.LinkedImageName },
             "pkg_plans": [ pkg.client.pkgplan.PkgPlan ],
@@ -157,9 +157,10 @@
                 self._cfg_mediators = {}
                 self._varcets_change = False
                 self._new_variants = None
-                self._changed_facets = pkg.facet.Facets()
-                self._removed_facets = set()
+                self._old_facets = None
                 self._new_facets = None
+                self._facet_change = False
+                self._masked_facet_change = False
                 self._new_mediators = collections.defaultdict(set)
                 self._mediators_change = False
                 self._new_avoid_obs = (set(), set())
@@ -172,6 +173,7 @@
                 self.li_ppkgs = frozenset()
                 self.li_ppubs = None
                 self.li_props = {}
+                self._li_pkg_updates = True
 
                 #
                 # Properties set when state >= EVALUATED_OK
@@ -198,6 +200,7 @@
                 self._need_boot_archive = None
                 # child properties
                 self.child_op = None
+                self.child_op_implicit = False
                 self.child_kwargs = {}
                 self.children_ignored = None
                 self.children_planned = []
@@ -462,29 +465,92 @@
                 before it was salvaged, and 'salvage_path' is where the item was
                 moved to.  This property is only valid after plan execution
                 has completed."""
-                assert self.executed
                 return self._salvaged
 
         @property
         def varcets(self):
-                """Returns a tuple of two lists containing the facet and variant
-                changes in this plan."""
+                """Returns a tuple of two lists containing the facet and
+                variant changes in this plan.
+
+                The variant list contains tuples with the following format:
+
+                    (<variant>, <new-value>)
+
+                The facet list contains tuples with the following format:
+
+                    (<facet>, <new-value>, <old-value>, <source>,
+                        <new-masked>, <old-masked>)
+
+                """
+
                 vs = []
                 if self._new_variants:
                         vs = self._new_variants.items()
+
+                # sort results by variant name
+                vs.sort(key=lambda x: x[0])
+
                 fs = []
-                fs.extend(self._changed_facets.items())
-                fs.extend([(f, None) for f in self._removed_facets])
+                if self._new_facets is None:
+                        return (vs, fs)
+
+                # create new dictionaries that index facets by name and
+                # source:
+                #    dict[(<facet, src>)] = (<value>, <masked>)
+                old_facets = dict([
+                    ((f, src), (v, masked))
+                    for f in self._old_facets
+                    # W0212 Access to a protected member
+                    # pylint: disable=W0212
+                    for v, src, masked in self._old_facets._src_values(f)
+                ])
+                new_facets = dict([
+                    ((f, src), (v, masked))
+                    for f in self._new_facets
+                    # W0212 Access to a protected member
+                    # pylint: disable=W0212
+                    for v, src, masked in self._new_facets._src_values(f)
+                ])
+
+                # check for removed facets
+                for f, src in set(old_facets) - set(new_facets):
+                        v, masked = old_facets[f, src]
+                        fs.append((f, None, v, src, masked, False))
+
+                # check for added facets
+                for f, src in set(new_facets) - set(old_facets):
+                        v, masked = new_facets[f, src]
+                        fs.append((f, v, None, src, False, masked))
+
+                # check for changing facets
+                for f, src in set(old_facets) & set(new_facets):
+                        if old_facets[f, src] == new_facets[f, src]:
+                                continue
+                        v_old, m_old = old_facets[f, src]
+                        v_new, m_new = new_facets[f, src]
+                        fs.append((f, v_new, v_old, src, m_old, m_new))
+
+                # sort results by facet name
+                fs.sort(key=lambda x: x[0])
+
                 return (vs, fs)
 
         def get_varcets(self):
                 """Returns a formatted list of strings representing the
                 variant/facet changes in this plan"""
                 vs, fs = self.varcets
-                ret = []
-                ret.extend(["variant %s: %s" % a for a in vs])
-                ret.extend(["  facet %s: %s" % a for a in fs])
-                return ret
+                rv = [
+                    "variant %s: %s" % (name[8:], val)
+                    for (name, val) in vs
+                ]
+                masked_str = _(" (masked)")
+                for name, v_new, v_old, src, m_old, m_new in fs:
+                        m_old = m_old and masked_str or ""
+                        m_new = m_new and masked_str or ""
+                        msg = "  facet %s (%s): %s%s -> %s%s" % \
+                            (name[6:], src, v_old, m_old, v_new, m_new)
+                        rv.append(msg)
+                return rv
 
         def get_changes(self):
                 """A generation function that yields tuples of PackageInfo
@@ -501,10 +567,17 @@
                 and 'dest_pi' is the new version of the package it is
                 being upgraded to."""
 
-                for pp in sorted(self.pkg_plans,
-                    key=operator.attrgetter("origin_fmri", "destination_fmri")):
-                        yield (PackageInfo.build_from_fmri(pp.origin_fmri),
-                            PackageInfo.build_from_fmri(pp.destination_fmri))
+                key = operator.attrgetter("origin_fmri", "destination_fmri")
+                for pp in sorted(self.pkg_plans, key=key):
+                        sfmri = pp.origin_fmri
+                        dfmri = pp.destination_fmri
+                        if sfmri == dfmri:
+                                sinfo = dinfo = PackageInfo.build_from_fmri(
+                                    sfmri)
+                        else:
+                                sinfo = PackageInfo.build_from_fmri(sfmri)
+                                dinfo = PackageInfo.build_from_fmri(dfmri)
+                        yield (sinfo, dinfo)
 
         def get_actions(self):
                 """A generator function that yields action change descriptions
@@ -670,3 +743,11 @@
         def cbytes_avail(self):
                 """Estimated number of bytes available in download cache"""
                 return self._cbytes_avail
+
+        @property
+        def new_facets(self):
+                """If facets are changing, this is the new set of facets being
+                applied."""
+                if self._new_facets is None:
+                        return None
+                return pkg.facet.Facets(self._new_facets)
--- a/src/modules/client/progress.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/progress.py	Wed Aug 14 11:12:35 2013 +0530
@@ -450,9 +450,12 @@
 
                 # See if we indeed met our goal.
                 if goalcheck and not self.metgoal():
-                        exstr = _("Goal mismatch '%s': "
-                            "expected goal: %s, current value: %s") % \
-                            (self.name, str(self.goalitems), str(self.items))
+                        exstr = _("Goal mismatch '%(name)s': "
+                            "expected goal: %(expected)s, "
+                            "current value: %(current)s") % \
+                            {"name": self.name,
+                            "expected": self.goalitems,
+                            "current": self.items}
                         logger.error("\n" + exstr)
                         assert self.metgoal(), exstr
 
@@ -631,6 +634,9 @@
         @pt_abstract
         def _li_recurse_progress_output(self, lin): pass
 
+        @pt_abstract
+        def _reversion(self, pfmri, outspec): pass
+
 class ProgressTrackerFrontend(object):
         """This essentially abstract class forms the interface that other
         modules in the system use to record progress against various goals."""
@@ -999,6 +1005,18 @@
                 """Call to indicate that the named child made progress."""
                 pass
 
+        @pt_abstract
+        def reversion_start(self, goal_pkgs, goal_revs): pass
+
+        @pt_abstract
+        def reversion_add_progress(self, pfmri, pkgs=0, reversioned=0,
+            adjusted=0):
+                pass
+
+        @pt_abstract
+        def reversion_done(self): pass
+
+
 class ProgressTracker(ProgressTrackerFrontend, ProgressTrackerBackend):
         """This class is used by the client to render and track progress
         towards the completion of various tasks, such as download,
@@ -1068,6 +1086,11 @@
                 self.archive_items = GoalTrackerItem(_("Archived items"))
                 self.archive_bytes = GoalTrackerItem(_("Archived bytes"))
 
+                # reversioning support
+                self.reversion_pkgs = GoalTrackerItem(_("Processed Packages"))
+                self.reversion_revs = GoalTrackerItem(_("Reversioned Packages"))
+                self.reversion_adjs = GoalTrackerItem(_("Adjusted Packages"))
+
                 # Used to measure elapsed time of entire planning; not otherwise
                 # rendered to the user.
                 self.plan_generic = TrackerItem("")
@@ -1502,11 +1525,14 @@
         def job_start(self, jobid, goal=None):
                 jobitem = self._jobitems[jobid]
                 jobitem.reset()
+                outspec = OutSpec()
                 if goal:
                         if not isinstance(jobitem, GoalTrackerItem):
                                 raise RuntimeError(
                                     "can't set goal on non-goal tracker")
                         jobitem.goalitems = goal
+                jobitem.printed = True
+                self._job_output(outspec, jobitem)
 
         def job_add_progress(self, jobid, nitems=1):
                 jobitem = self._jobitems[jobid]
@@ -1657,6 +1683,33 @@
                 """Call to indicate that the named child made progress."""
                 self._li_recurse_progress_output(lin)
 
+        def reversion_start(self, goal_pkgs, goal_revs):
+                self.reversion_adjs.reset()
+                self.reversion_revs.reset()
+                self.reversion_pkgs.reset()
+                self.reversion_revs.goalitems = goal_revs 
+                self.reversion_pkgs.goalitems = goal_pkgs
+                self.reversion_adjs.goalitems = -1 
+
+        def reversion_add_progress(self, pfmri, pkgs=0, reversioned=0,
+            adjusted=0):
+                outspec = OutSpec()
+                if not self.reversion_pkgs.printed:
+                        self.reversion_pkgs.printed = True
+                        outspec.first = True
+                
+                self.reversion_revs.items += reversioned
+                self.reversion_adjs.items += adjusted
+                self.reversion_pkgs.items += pkgs
+                self._reversion(pfmri, outspec)
+
+        def reversion_done(self):
+                self.reversion_pkgs.done()
+                self.reversion_revs.done()
+                self.reversion_adjs.done(goalcheck=False)
+                if self.reversion_pkgs.printed:
+                        self._reversion("Done", OutSpec(last=True))
+
 
 class MultiProgressTracker(ProgressTrackerFrontend):
         """This class is a proxy, dispatching incoming progress tracking calls
@@ -1869,8 +1922,15 @@
                 if self.major_phase == self.PHASE_UTILITY:
                         return ""
 
-                return _("%*s: ") % (self.phase_max_width,
-                    self.phase_names[self.major_phase])
+                # The following string was originally expressed as
+                # "%*s: " % \
+                #     (self.phase_max_width, self.phase_names[self.major_phase])
+                # however xgettext incorrectly flags this as an improper use of
+                # non-parameterized messages, which gets detected as an error
+                # during our build.  So instead, we express the string using
+                # an equivalent <str>.format(..) function
+                s = _("{phase:>%d}: ") % self.phase_max_width
+                return s.format(phase=self.phase_names[self.major_phase])
 
         #
         # Helper routines
@@ -1977,8 +2037,10 @@
                 # adjusts the output based on the major phase.
                 #
                 self._pe.cprint(self._phase_prefix() +
-                    _("Fetching manifests: %s  %d%% complete") %
-                    (self.mfst_fetch.pair(), self.mfst_fetch.pctdone()))
+                    _("Fetching manifests: %(num)s  %(pctcomplete)d%% "
+                    "complete") %
+                    {"num": self.mfst_fetch.pair(),
+                    "pctcomplete": self.mfst_fetch.pctdone()})
 
         def _mfst_commit(self, outspec):
                 # For now, manifest commit is hard to handle in this
@@ -2051,15 +2113,19 @@
                         mbs = format_pair("%.1f", self.dl_bytes.items,
                             self.dl_bytes.goalitems, scale=(1024 * 1024))
                         self._pe.cprint(
-                            _("Download: %s items  %sMB  %d%% complete %s") %
-                            (self.dl_files.pair(), mbs, self.dl_bytes.pctdone(),
-                            speedstr))
+                            _("Download: %(num)s items  %(mbs)sMB  "
+                            "%(pctcomplete)d%% complete %(speed)s") %
+                            {"num": self.dl_files.pair(), "mbs": mbs,
+                            "pctcomplete": self.dl_bytes.pctdone(),
+                            "speed": speedstr})
                 else:
                         # 'last'
                         goal = misc.bytes_to_str(self.dl_bytes.goalitems)
                         self.__generic_done(
-                            msg=_("Download: Completed %s in %.2f seconds %s") %
-                            (goal, self.dl_estimator.elapsed(), speedstr))
+                            msg=_("Download: Completed %(num)s in %(sec).2f "
+                            "seconds %(speed)s") %
+                            {"num": goal, "sec": self.dl_estimator.elapsed(),
+                            "speed": speedstr})
 
         def _republish_output(self, outspec):
                 if "startpkg" in outspec.changed:
@@ -2079,16 +2145,18 @@
                 if outspec.last:
                         goal = misc.bytes_to_str(self.archive_bytes.goalitems)
                         self.__generic_done(
-                            msg=_("Archiving: Completed %s in %.2f seconds") %
-                            (goal, self.archive_items.elapsed()))
+                            msg=_("Archiving: Completed %(num)s in %(secs).2f "
+                            "seconds") %
+                            {"num": goal, "secs": self.archive_items.elapsed()})
                         return
 
                 mbs = format_pair("%.1f", self.archive_bytes.items,
                     self.archive_bytes.goalitems, scale=(1024 * 1024))
                 self._pe.cprint(
-                    _("Archiving: %s items  %sMB  %d%% complete") %
-                    (self.archive_items.pair(), mbs,
-                    self.archive_bytes.pctdone()))
+                    _("Archiving: %(pair)s items  %(mbs)sMB  %(pctcomplete)d%% "
+                    "complete") %
+                    {"pair": self.archive_items.pair(), "mbs": mbs,
+                    "pctcomplete": self.archive_bytes.pctdone()})
 
         #
         # The progress tracking infrastructure wants to tell us about each
@@ -2105,9 +2173,10 @@
                     sum(x.items for x in self._actionitems.values())
                 total_goal = \
                     sum(x.goalitems for x in self._actionitems.values())
-                self._pe.cprint(self._phase_prefix() + _("%s actions (%s)") %
-                    (format_pair("%d", total_actions, total_goal),
-                    actionitem.name))
+                self._pe.cprint(self._phase_prefix() +
+                    _("%(num)s actions (%(type)s)") %
+                    {"num": format_pair("%d", total_actions, total_goal),
+                    "type": actionitem.name})
 
         def _act_output_all_done(self):
                 total_goal = \
@@ -2117,8 +2186,9 @@
                 if total_goal == 0:
                         return
                 self._pe.cprint(self._phase_prefix() +
-                    _("Completed %d actions in %.2f seconds.") %
-                    (total_goal, total_time))
+                    _("Completed %(numactions)d actions in %(time).2f "
+                    "seconds.") %
+                    {"numactions": total_goal, "time": total_time})
 
         def _job_output(self, outspec, jobitem):
                 if outspec.first:
@@ -2179,15 +2249,41 @@
                         return
 
                 running = " ".join([str(i) for i in self.linked_running])
-                msg = _("Linked images: %s done; %d working: %s") % \
-                    (format_pair("%d", done, self.linked_total),
-                    len(self.linked_running), running)
+                msg = _("Linked images: %(pair)s done; %(numworking)d working: "
+                    "%(running)s") % \
+                    {"pair": format_pair("%d", done, self.linked_total),
+                    "numworking": len(self.linked_running),
+                    "running": running}
                 self._pe.cprint(self._phase_prefix() + msg)
 
         def _li_recurse_progress_output(self, lin):
                 if self.linked_pkg_op == pkgdefs.PKG_OP_PUBCHECK:
                         return
 
+        def _reversion(self, pfmri, outspec):
+                if not self._ptimer.time_to_print() and not outspec:
+                        return
+
+                if outspec.first:
+                        # tell ptimer that we just printed.
+                        self._ptimer.reset_now()
+
+                if outspec.last:
+                        self.__generic_done(
+                            msg=_("Reversioned %(revs)s of %(pkgs)s packages "
+                            "and adjusted %(adjs)s packages.") %
+                            {"revs": self.reversion_revs.items,
+                            "pkgs": self.reversion_pkgs.items,
+                            "adjs": self.reversion_adjs.items})
+                        return
+
+                self._pe.cprint(
+                    _("Reversioning: %(pkgs)s processed, %(revs)s reversioned, "
+                    "%(adjs)s adjusted") %
+                    {"pkgs": self.reversion_pkgs.pair(),
+                    "revs": self.reversion_revs.pair(),
+                    "adjs": self.reversion_adjs.items})
+
 
 class LinkedChildProgressTracker(CommandLineProgressTracker):
         """This tracker is used for recursion with linked children.
@@ -2351,8 +2447,10 @@
                 extra_info = ""
                 if isinstance(planitem, GoalTrackerItem):
                         extra_info = ": %s" % planitem.pair()
-                msg = _("Creating Plan (%s%s): %s") % \
-                    (planitem.name, extra_info, self._spinner())
+                msg = _("Creating Plan (%(name)s%(info)s): %(spinner)s") % \
+                    {"name": planitem.name,
+                    "info": extra_info,
+                    "spinner": self._spinner()}
                 self._pe.cprint(msg, sep='', end='', erase=True)
 
         def _plan_output_all_done(self):
@@ -2373,17 +2471,48 @@
                 # the output based on the major mode.
                 #
                 if self.major_phase == self.PHASE_PLAN:
-                        msg = _("Creating Plan (%s %s) %c") % \
-                            (self.mfst_fetch.name, self.mfst_fetch.pair(),
-                                self._spinner())
+                        msg = _("Creating Plan (%(name)s %(pair)s) "
+                            "%(spinner)c") % \
+                            {"name": self.mfst_fetch.name,
+                            "pair": self.mfst_fetch.pair(),
+                            "spinner": self._spinner()}
                 if self.major_phase == self.PHASE_UTILITY:
-                        msg = _("%s (%s) %c") % (self.mfst_fetch.name,
-                            self.mfst_fetch.pair(), self._spinner())
+                        # note to translators: the position of these strings
+                        # should probably be left alone, as they form part of
+                        # the progress output text.
+                        msg = _("%(name)s (%(fetchpair)s) %(spinchar)c") % {
+                            "name": self.mfst_fetch.name,
+                            "fetchpair": self.mfst_fetch.pair(),
+                            "spinchar": self._spinner()}
                 self._pe.cprint(msg, sep='', end='', erase=True)
 
                 if outspec.last:
                         self.__generic_done()
 
+        def _reversion(self, pfmri, outspec):
+
+                if not self._ptimer.time_to_print() and not outspec:
+                        return
+
+                if isinstance(pfmri, pkg.fmri.PkgFmri):
+                        stem = pfmri.get_pkg_stem(anarchy=True)
+                else:
+                        stem = pfmri
+
+                # The first time, emit header.
+                if outspec.first:
+                        self._pe.cprint("%-38s %13s %13s %11s" %
+                            (_("PKG"), _("Processed"), _("Reversioned"),
+                            _("Adjusted")))
+
+                s = "%-40.40s %11s %13s %11s" % \
+                    (stem, self.reversion_pkgs.pair(),
+                    self.reversion_revs.pair(), self.reversion_adjs.items)
+                self._pe.cprint(s, end='', erase=True)
+
+                if outspec.last:
+                        self.__generic_done_newline()
+
         def _mfst_commit(self, outspec):
                 if self.purpose == self.PURPOSE_PKG_UPDATE_CHK:
                         self._up2date()
@@ -2662,10 +2791,12 @@
                 assert self.major_phase in self.li_phase_names, self.major_phase
 
                 running = " ".join([str(i) for i in self.linked_running])
-                msg = _("%s linked: %s done; %d working: %s") % \
-                    (self.li_phase_names[self.major_phase],
-                    format_pair("%d", done, self.linked_total),
-                    len(self.linked_running), running)
+                msg = _("%(phase)s linked: %(numdone)s done; "
+                    "%(numworking)d working: %(running)s") % \
+                    {"phase": self.li_phase_names[self.major_phase],
+                    "numdone": format_pair("%d", done, self.linked_total),
+                    "numworking": len(self.linked_running),
+                    "running": running}
                 self._pe.cprint(msg, erase=True)
 
                 self.__linked_spinners = list(
--- a/src/modules/client/publisher.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/publisher.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 #
@@ -1101,8 +1101,8 @@
         # These properties are declared here so that they show up in the pydoc
         # documentation as private, and for clarity in the property declarations
         # found near the end of the class definition.
+        _catalog = None
         __alias = None
-        __catalog = None
         __client_uuid = None
         __disabled = False
         __meta_root = None
@@ -1189,7 +1189,7 @@
                 self.__issuers = {}
 
                 # Must be done last.
-                self.__catalog = catalog
+                self._catalog = catalog
 
         def __cmp__(self, other):
                 if other is None:
@@ -1216,6 +1216,7 @@
                     revoked_ca_certs=self.revoked_ca_certs,
                     approved_ca_certs=self.approved_ca_certs,
                     sys_pub=self.sys_pub)
+                pub._catalog = self._catalog
                 pub._source_object_id = id(self)
                 return pub
 
@@ -1360,8 +1361,8 @@
                 if pathname:
                         pathname = os.path.abspath(pathname)
                 self.__meta_root = pathname
-                if self.__catalog:
-                        self.__catalog.meta_root = self.catalog_root
+                if self._catalog:
+                        self._catalog.meta_root = self.catalog_root
                 if self.__meta_root:
                         self.__origin_root = os.path.join(self.__meta_root,
                             "origins")
@@ -1379,7 +1380,7 @@
                 if not isinstance(value, Repository):
                         raise api_errors.UnknownRepository(value)
                 self.__repository = value
-                self.__catalog = None
+                self._catalog = None
 
         def __set_client_uuid(self, value):
                 self.__client_uuid = value
@@ -1478,11 +1479,11 @@
                 selected repository, or None if available."""
 
                 if not self.meta_root:
-                        if self.__catalog:
-                                return self.__catalog
+                        if self._catalog:
+                                return self._catalog
                         return None
 
-                if not self.__catalog:
+                if not self._catalog:
                         croot = self.catalog_root
                         if not os.path.isdir(croot):
                                 # Current meta_root structure is likely in
@@ -1491,9 +1492,9 @@
                                 # is desired instead.  (This can happen during
                                 # an image format upgrade.)
                                 croot = None
-                        self.__catalog = pkg.catalog.Catalog(
+                        self._catalog = pkg.catalog.Catalog(
                             meta_root=croot)
-                return self.__catalog
+                return self._catalog
 
         @property
         def catalog_root(self):
@@ -1674,7 +1675,7 @@
 
                 # Discard existing catalog.
                 self.catalog.destroy()
-                self.__catalog = None
+                self._catalog = None
 
                 # Ensure all old catalog files are removed.
                 for entry in os.listdir(self.catalog_root):
@@ -1688,11 +1689,13 @@
 
                 # If there's only one origin, then just symlink its catalog
                 # files into place.
+                # Symlinking includes updates for publication tools.
                 opaths = [entry for entry in self.__gen_origin_paths()]
                 if len(opaths) == 1:
                         opath = opaths[0][1]
                         for fname in os.listdir(opath):
-                                if fname.startswith("catalog."):
+                                if fname.startswith("catalog.") or \
+                                    fname.startswith("update."):
                                         src = os.path.join(opath, fname)
                                         dest = os.path.join(self.catalog_root,
                                             fname)
@@ -1847,7 +1850,7 @@
                         # avoids many of the problems that could happen due to
                         # deficiencies in the v0 implementation.
                         v1_cat.destroy()
-                        self.__catalog = None
+                        self._catalog = None
                         v1_cat = pkg.catalog.Catalog(meta_root=v1_root,
                             sign=False)
 
@@ -1946,7 +1949,7 @@
                 return False, True
 
         def __refresh_v1(self, croot, tempdir, full_refresh, immediate,
-            mismatched, repo, progtrack=None):
+            mismatched, repo, progtrack=None, include_updates=False):
                 """The method to refresh the publisher's metadata against
                 a catalog/1 source.  If the more recent catalog/1 version
                 isn't supported, __refresh_v0 is invoked as a fallback.
@@ -1975,7 +1978,7 @@
                         if v1_cat.exists:
                                 # Ensure v1 -> v0 transition works right.
                                 v1_cat.destroy()
-                                self.__catalog = None
+                                self._catalog = None
                         return self.__refresh_v0(croot, full_refresh, immediate,
                             repo)
 
@@ -2003,6 +2006,9 @@
                                 if locale != "C":
                                         continue
                                 flist.append(name)
+                        if include_updates:
+                                for update in attrs.updates:
+                                        flist.append(update)
 
                 if flist:
                         # More catalog files to retrieve.
@@ -2018,8 +2024,8 @@
                                 return self.__refresh_v0(croot, full_refresh,
                                     immediate, repo)
 
-                # Clear __catalog, so we'll read in the new catalog.
-                self.__catalog = None
+                # Clear _catalog, so we'll read in the new catalog.
+                self._catalog = None
                 v1_cat = pkg.catalog.Catalog(meta_root=croot)
 
                 # At this point the client should have a set of the constituent
@@ -2062,7 +2068,7 @@
                 return True, True
 
         def __refresh_origin(self, croot, full_refresh, immediate, mismatched,
-            origin, progtrack=None):
+            origin, progtrack=None, include_updates=False):
                 """Private helper method used to refresh catalog data for each
                 origin.  Returns a tuple of (changed, refreshed) where 'changed'
                 indicates whether new catalog data was found and 'refreshed'
@@ -2092,7 +2098,8 @@
                 try:
                         rval = self.__refresh_v1(croot, tempdir,
                             full_refresh, immediate, mismatched, repo,
-			    progtrack=progtrack)
+			    progtrack=progtrack,
+                            include_updates=include_updates)
 
                         # Perform publisher metadata sanity checks.
                         self.__validate_metadata(croot, repo)
@@ -2103,7 +2110,7 @@
                         shutil.rmtree(tempdir, True)
 
         def __refresh(self, full_refresh, immediate, mismatched=False,
-	    progtrack=None):
+	    progtrack=None, include_updates=False):
                 """The method to handle the overall refresh process.  It
                 determines if a refresh is actually needed, and then calls
                 the first version-specific refresh method in the chain."""
@@ -2139,7 +2146,8 @@
                 for origin, opath in self.__gen_origin_paths():
                         changed, refreshed = self.__refresh_origin(opath,
                             full_refresh, immediate, mismatched, origin,
-			    progtrack=progtrack)
+			    progtrack=progtrack,
+                            include_updates=include_updates)
                         if changed:
                                 any_changed = True
                         if refreshed:
@@ -2156,7 +2164,8 @@
 
                 return any_changed
 
-        def refresh(self, full_refresh=False, immediate=False, progtrack=None):
+        def refresh(self, full_refresh=False, immediate=False, progtrack=None,
+            include_updates=False):
                 """Refreshes the publisher's metadata, returning a boolean
                 value indicating whether any updates to the publisher's
                 metadata occurred.
@@ -2169,11 +2178,16 @@
                 'immediate' is an optional boolean value indicating whether
                 a refresh should occur now.  If False, a publisher's selected
                 repository will be checked for updates only if needs_refresh
-                is True."""
+                is True.
+
+                'include_updates' is an optional boolean value indicating
+                whether all catalog updates should be retrieved additionally to
+                the catalog."""
 
                 try:
                         return self.__refresh(full_refresh, immediate,
-			    progtrack=progtrack)
+			    progtrack=progtrack,
+                            include_updates=include_updates)
                 except (api_errors.BadCatalogUpdateIdentity,
                     api_errors.DuplicateCatalogEntry,
                     api_errors.ObsoleteCatalogUpdate,
--- a/src/modules/client/transport/repo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/transport/repo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import cStringIO
@@ -447,7 +447,7 @@
                 # Only append the publisher prefix if the publisher of the
                 # request is known, not already part of the URI, if this isn't
                 # an open operation, and if the repository supports version 1
-                # of the publisher opation.  The prefix shouldn't be appended
+                # of the publisher operation.  The prefix shouldn't be appended
                 # for open because the publisher may not yet be known to the
                 # repository, and not in other cases because the repository
                 # doesn't support it.
@@ -1060,12 +1060,11 @@
                 its headers then we can try the request with that additional
                 header, which can help where a web cache is serving corrupt
                 content.
-
-                This method returns True if the headers passed haven't got
-                "Cache-Control: no-cache" set, adding that header.  Otherwise
-                it returns False.
                 """
 
+                if header is None:
+                        header = {}
+
                 if header.get("Cache-Control", "") != "no-cache":
                         header["Cache-Control"] = "no-cache"
                         header["Pragma"] = "no-cache"
@@ -1116,12 +1115,14 @@
                     proxy=self._repouri.proxy)
 
         def _post_url(self, url, data=None, header=None, ccancel=None,
-            data_fobj=None, data_fp=None, failonerror=True):
+            data_fobj=None, data_fp=None, failonerror=True, progclass=None,
+            progtrack=None):
                 return self._engine.send_data(url, data=data, header=header,
                     sslcert=self._repouri.ssl_cert,
                     sslkey=self._repouri.ssl_key, repourl=self._url,
                     ccancel=ccancel, data_fobj=data_fobj,
                     data_fp=data_fp, failonerror=failonerror,
+                    progclass=progclass, progtrack=progtrack,
                     runtime_proxy=self._repouri.runtime_proxy,
                     proxy=self._repouri.proxy)
 
--- a/src/modules/client/transport/transport.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/client/transport/transport.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import cStringIO
@@ -204,6 +204,16 @@
                 """
                 raise NotImplementedError
 
+        def get_pkg_sigs(self, fmri, pub):
+                """Returns a dictionary of the signature data found in the
+                catalog for the given package FMRI and Publisher object or None
+                if no catalog is available."""
+
+                # Check provided publisher's catalog for signature data.
+                if pub.catalog:
+                        return dict(pub.catalog.get_entry_signatures(
+                            fmri))
+
         def get_pkg_alt_repo(self, pfmri):
                 """Returns the repository object containing the origins that
                 should be used to retrieve the specified package or None.
@@ -226,9 +236,8 @@
         def get_publisher(self, publisher_name):
                 raise NotImplementedError
 
-        def reset_caches(self, shared=False):
-                """Discard any cache information and reconfigure based on
-                current publisher configuration data.
+        def clear_caches(self, shared=False):
+                """Discard any cache information.
 
                 'shared' is an optional boolean value indicating that any
                 shared cache information (caches not specific to any publisher)
@@ -246,6 +255,19 @@
                                 # used.
                                 del self.__caches[pub]
 
+        def reset_caches(self, shared=False):
+                """Discard any cache information and reconfigure based on
+                current publisher configuration data.
+
+                'shared' is an optional boolean value indicating that any
+                shared cache information (caches not specific to any publisher)
+                should also be discarded.  If True, callers are responsible for
+                ensuring a new set of shared cache information is added again.
+                """
+
+                # Clear the old cache setup.
+                self.clear_caches(shared=shared)
+
                 # Automatically add any publisher repository origins
                 # or mirrors that are filesystem-based as read-only caches.
                 for pub in self.gen_publishers():
@@ -343,6 +365,26 @@
 
                 return self.__img.get_manifest_path(pfmri)
 
+        def get_pkg_sigs(self, fmri, pub):
+                """Returns a dictionary of the signature data found in the
+                catalog for the given package FMRI and Publisher object or None
+                if no catalog is available."""
+
+                # Check publisher for entry first.
+                try:
+                        sigs = TransportCfg.get_pkg_sigs(self, fmri, pub)
+                except apx.UnknownCatalogEntry:
+                        sigs = None
+
+                if sigs is None:
+                        # Either package was unknown or publisher catalog
+                        # contained no signature data.  Fallback to the known
+                        # catalog as temporary sources may be in use.
+                        kcat = self.__img.get_catalog(
+                            self.__img.IMG_CATALOG_KNOWN)
+                        return dict(kcat.get_entry_signatures(fmri))
+                return sigs
+
         def get_pkg_alt_repo(self, pfmri):
                 """Returns the repository object containing the origins that
                 should be used to retrieve the specified package or None.
@@ -602,10 +644,16 @@
                 # of origins for a publisher without incurring the significant
                 # overhead of performing file-based search unless the network-
                 # based resource is unavailable.
+                no_result_url = None
                 for d, retries, v in self.__gen_repo(pub, retry_count,
                     origin_only=True, prefer_remote=True, alt_repo=alt_repo,
                     operation="search", versions=[0, 1]):
 
+                        if retries == 1:
+                                no_result_url = None
+                        elif retries > 1 and no_result_url:
+                                continue
+
                         try:
                                 fobj = d.do_search(data, header,
                                     ccancel=ccancel, pub=pub)
@@ -633,8 +681,8 @@
                                         raise apx.UnsupportedSearchError(e.url,
                                             "search/1")
                                 elif e.code == httplib.NO_CONTENT:
-                                        raise apx.NegativeSearchResult(e.url)
-                                elif e.code == (httplib.BAD_REQUEST,
+                                        no_result_url = e.url
+                                elif e.code in (httplib.BAD_REQUEST,
                                     errno.EINVAL):
                                         raise apx.MalformedSearchRequest(e.url)
                                 elif e.retryable:
@@ -648,8 +696,10 @@
                                         fobj = None
                                 else:
                                         raise
-
-                raise failures
+                if no_result_url:
+                        raise apx.NegativeSearchResult(no_result_url)
+                else:
+                        raise failures
 
         def get_ca_dir(self):
                 """Return the path to the directory that contains CA
@@ -753,15 +803,15 @@
         @staticmethod
         def _verify_catalog(filename, dirname):
                 """A wrapper for catalog.verify() that catches
-                BadCatalogSignatures exceptions and translates them to
-                the appropriate InvalidContentException that the transport
-                uses for content verification."""
+                CatalogErrors and translates them to the appropriate
+                InvalidContentException that the transport uses for content
+                verification."""
 
                 filepath = os.path.join(dirname, filename)
 
                 try:
                         catalog.verify(filepath)
-                except (apx.BadCatalogSignatures, apx.InvalidCatalogFile), e:
+                except apx.CatalogError, e:
                         os.remove(filepath)
                         te = tx.InvalidContentException(filepath,
                             "CatalogPart failed validation: %s" % e)
@@ -991,7 +1041,8 @@
 
                         except apx.InvalidP5IFile, e:
                                 repouri_key = d.get_repouri_key()
-                                exc = tx.TransferContentException(url[0],
+                                exc = tx.TransferContentException(
+                                    repouri_key[0],
                                     "api_errors.InvalidP5IFile:%s" %
                                     (" ".join([str(a) for a in e.args])))
                                 repostats = self.stats[repouri_key]
@@ -1113,7 +1164,8 @@
                                 failures.extend(e.failures)
 
                         except zlib.error, e:
-                                exc = tx.TransferContentException(repouri_key[0],
+                                exc = tx.TransferContentException(
+                                    repouri_key[0],
                                     "zlib.error:%s" %
                                     (" ".join([str(a) for a in e.args])),
                                     proxy=repouri_key[1])
@@ -1163,7 +1215,8 @@
 
                         except (TypeError, ValueError), e:
                                 
-                                exc = tx.TransferContentException(repouri_key[0],
+                                exc = tx.TransferContentException(
+                                    repouri_key[0],
                                     "Invalid stats response: %s" % e,
                                     proxy=repouri_key[1])
                                 repostats.record_error(content=True)
@@ -1570,41 +1623,55 @@
                 the manifest content in 'content'.  One of these arguments
                 must be used."""
 
+                # Bail if manifest validation has been turned off for
+                # debugging/testing purposes.
+                if DebugValues.get("manifest_validate") == "Never":
+                        return True
+
+                must_verify = \
+                    DebugValues.get("manifest_validate") == "Always"
+
                 if not isinstance(pub, publisher.Publisher):
                         # Get publisher using information from FMRI.
                         try:
                                 pub = self.cfg.get_publisher(fmri.publisher)
                         except apx.UnknownPublisher:
+                                if must_verify:
+                                        assert False, \
+                                            "Did not validate manifest; " \
+                                            "unknown publisher %s (%s)." % \
+                                            (fmri.publisher, fmri)
                                 return False
 
-                # Handle case where publisher has no Catalog.
-                if not pub.catalog:
-                        return False
-
-                # Use the publisher to get the catalog and its signature info.
                 try:
-                        sigs = dict(pub.catalog.get_entry_signatures(fmri))
+                        sigs = self.cfg.get_pkg_sigs(fmri, pub)
                 except apx.UnknownCatalogEntry:
+                        if must_verify:
+                                assert False, "Did not validate manifest; " \
+                                    "couldn't find sigs."
                         return False
 
                 if sigs and "sha-1" in sigs:
                         chash = sigs["sha-1"]
                 else:
+                        if must_verify:
+                                assert False, \
+                                    "Did not validate manifest; no sha-1 sig."
                         return False
 
                 if mfstpath:
                         mf = file(mfstpath)
                         mcontent = mf.read()
                         mf.close()
-                elif content:
+                elif content is not None:
                         mcontent = content
                 else:
                         raise ValueError("Caller must supply either mfstpath "
                             "or content arguments.")
 
                 newhash = manifest.Manifest.hash_create(mcontent)
-                if chash != newhash and \
-                    DebugValues.get("manifest_validation") != "False":
+
+                if chash != newhash:
                         if mfstpath:
                                 sz = os.stat(mfstpath).st_size
                                 os.remove(mfstpath)
@@ -1614,7 +1681,6 @@
                             "manifest hash failure: fmri: %s \n"
                             "expected: %s computed: %s" %
                             (fmri, chash, newhash), size=sz)
-
                 return True
 
         @staticmethod
@@ -2129,6 +2195,7 @@
 
                 CHUNK_SMALL = 10
                 CHUNK_LARGE = 100
+                CHUNK_HUGE = 1024
 
                 # Call setup if the transport isn't configured or was shutdown.
                 if not self.__engine:
@@ -2153,6 +2220,8 @@
                 repolist = _convert_repouris(repolist)
                 n = len(repolist)
                 m = self.stats.get_num_visited(repolist)
+                if n == 1:
+                        return CHUNK_HUGE
                 if m < n:
                         return CHUNK_SMALL
                 return CHUNK_LARGE
@@ -3036,10 +3105,15 @@
         are used to identify and verify the content.  Additional parameters
         define what happens when download finishes successfully."""
 
-        def __init__(self, pub, xport, final_dir, decompress=False,
+        def __init__(self, pub, xport, final_dir=None, decompress=False,
             progtrack=None, ccancel=None, alt_repo=None):
                 """Supply the destination publisher in the pub argument.
-                The transport object should be passed in xport."""
+                The transport object should be passed in xport.
+                
+                'final_dir' indicates the directory the retrieved files should
+                be moved to after retrieval. If it is set to None, files will
+                not be moved and remain in the cache directory specified
+                in the 'xport' object."""
 
                 MultiFile.__init__(self, pub, xport, progtrack=progtrack,
                     ccancel=ccancel, alt_repo=alt_repo)
@@ -3057,7 +3131,7 @@
                     self.get_publisher())
                 hashval = action.hash
 
-                if cpath:
+                if cpath and self._final_dir:
                         self._final_copy(hashval, cpath)
                         if self._progtrack:
                                 filesz = int(misc.get_pkg_otw_size(action))
@@ -3069,7 +3143,7 @@
                         for c in action.get_chain_certs():
                                 cpath = self._transport._action_cached(action,
                                     self.get_publisher(), in_hash=c)
-                                if cpath:
+                                if cpath and self._final_dir:
                                         self._final_copy(c, cpath)
                                         if self._progtrack:
                                                 self._progtrack.download_add_progress(
@@ -3123,7 +3197,8 @@
                         self._progtrack.download_add_progress((nactions - 1),
                             nbytes)
 
-                self._final_copy(hashval, current_path)
+                if self._final_dir:
+                        self._final_copy(hashval, current_path)
                 self.del_hash(hashval)
 
         def _final_copy(self, hashval, current_path):
--- a/src/modules/depotcontroller.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/depotcontroller.py	Wed Aug 14 11:12:35 2013 +0530
@@ -68,10 +68,15 @@
                 self.__state = self.HALTED
                 self.__writable_root = None
                 self.__sort_file_max_size = None
+                self.__ssl_dialog = None
+                self.__ssl_cert_file = None
+                self.__ssl_key_file = None
                 self.__starttime = 0
                 self.__wrapper_start = []
                 self.__wrapper_end = wrapper_end
                 self.__env = {}
+                self.__nasty = None
+                self.__nasty_sleep = None
                 if wrapper_start:
                         self.__wrapper_start = wrapper_start
                 if env:
@@ -209,7 +214,13 @@
                                 host = "[%s]" % host
                 else:
                         host = "localhost"
-                return "http://%s:%d" % (host, self.__port)
+
+                if self.__ssl_key_file:
+                        scheme = "https"
+                else:
+                        scheme = "http"
+
+                return "%s://%s:%d" % (scheme, host, self.__port)
 
         def set_writable_root(self, wr):
                 self.__writable_root = wr
@@ -235,6 +246,35 @@
         def unset_disable_ops(self):
                 self.__disable_ops = None
 
+        def set_nasty(self, nastiness):
+                """Set the nastiness level of the depot.  Also works on
+                running depots."""
+                self.__nasty = nastiness
+                if self.__depot_handle != None:
+                        nastyurl = urlparse.urljoin(self.get_depot_url(),
+                            "nasty/%d" % self.__nasty)
+                        url = urllib2.urlopen(nastyurl)
+                        url.close()
+
+        def get_nasty(self):
+                return self.__nasty
+
+        def set_nasty_sleep(self, sleep):
+                self.__nasty_sleep = sleep
+
+        def get_nasty_sleep(self):
+                return self.__nasty_sleep
+
+        def enable_ssl(self, key_path=None, cert_path=None, dialog=None):
+                self.__ssl_key_file = key_path
+                self.__ssl_cert_file = cert_path
+                self.__ssl_dialog = dialog
+
+        def disable_ssl(self):
+                self.__ssl_key_file = None
+                self.__ssl_cert_file = None
+                self.__ssl_dialog = None
+
         def __network_ping(self):
                 try:
                         repourl = urlparse.urljoin(self.get_depot_url(),
@@ -312,12 +352,22 @@
                         args.append("--exit-ready")
                 if self.__cfg_file:
                         args.append("--cfg-file=%s" % self.__cfg_file)
+                if self.__ssl_cert_file:
+                        args.append("--ssl-cert-file=%s" % self.__ssl_cert_file)
+                if self.__ssl_key_file:
+                        args.append("--ssl-key-file=%s" % self.__ssl_key_file)
+                if self.__ssl_dialog:
+                        args.append("--ssl-dialog=%s" % self.__ssl_dialog)
                 if self.__debug_features:
                         args.append("--debug=%s" % ",".join(
                             self.__debug_features))
                 if self.__disable_ops:
                         args.append("--disable-ops=%s" % ",".join(
                             self.__disable_ops))
+                if self.__nasty:
+                        args.append("--nasty %d" % self.__nasty)
+                if self.__nasty_sleep:
+                        args.append("--nasty-sleep %d" % self.__nasty_sleep)
                 for section in self.__props:
                         for prop, val in self.__props[section].iteritems():
                                 args.append("--set-property=%s.%s='%s'" %
--- a/src/modules/facet.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/facet.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,13 +21,13 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 # basic facet support
 
 from pkg._varcet import _allow_facet
-from pkg.misc import EmptyI
+from pkg.misc import EmptyI, ImmutableDict
 import fnmatch
 import re
 import types
@@ -37,92 +37,378 @@
         # and maintain ordered list of keys sorted
         # by length.
 
-        # subclass __getitem_ so that queries w/
+        # subclass __getitem__ so that queries w/
         # actual facets find match
 
+        #
+        # Facets can come from three different sources.
+        #
+        # SYSTEM facets are facets whose values are assigned by the system.
+        # These are usually facets defined in packages which are not set in an
+        # image, and the value assigned by the system is always true.  These
+        # facets will usually never be found in a Facets dictionary.  (Facets
+        # dictionaries only contain facets which are explicitly set.)
+        #
+        # LOCAL facets are facets which have been set locally in an image
+        # using pkg(1) or the pkg api.  Explicitly set LOCAL facets are stored
+        # in Facets.__local.  Facets which are not explicitly set but match an
+        # explicitly set LOCAL facet glob pattern are also considered to be
+        # LOCAL.
+        #
+        # PARENT facets are facets which are inherited from a parent image.
+        # they are managed internally by the packaging subsystem.  Explicitly
+        # inherited facets are stored in Facets.__inherited.  Facets which are
+        # not explicitly set but match an explicitly set PARENT facet glob
+        # pattern are also considered to be PARENT.
+        #
+        # When evaluating facets, all PARENT facets are evaluated before LOCAL
+        # facets.  This is done by ensuring that all PARENT facets come before
+        # any LOCAL facets in __keylist.  This is done because PARENT facets
+        # exist to propagate faceted dependencies between linked images, which
+        # is needed to ensure the solver can run successfully.  ie, if a
+        # parent image relaxes dependencies via facet version-locks, then the
+        # child needs to inherit those facets since otherwise it is more
+        # constrained in possible solutions than it's parent and likely won't
+        # be able to plan an update that keeps it in sync with it's parent.
+        #
+        # Sine PARENT facets take priority over LOCAL facets, it's possible to
+        # have conflicts between the two.  In the case where a facet is both
+        # inherited and set locally, both values are preserved, but the
+        # inherited value masks the local value.  Users can list and update
+        # local values while they are masked using pkg(1), but as long as the
+        # values are masked they will not affect image planning operations.
+        # Once an inherited facet that masks a local facet is removed, the
+        # local facet will be restored.
+        #
+
+        FACET_SRC_SYSTEM = "system"
+        FACET_SRC_LOCAL = "local"
+        FACET_SRC_PARENT = "parent"
+
         def __init__(self, init=EmptyI):
                 dict.__init__(self)
                 self.__keylist = []
                 self.__res = {}
-                for i in init:
-                        self[i] = init[i]
+                self.__local = {}
+                self.__local_ro = None
+                self.__inherited = {}
+                self.__inherited_ro = None
+
+                # initialize ourselves
+                self.update(init)
 
         @staticmethod
         def getstate(obj, je_state=None):
                 """Returns the serialized state of this object in a format
                 that that can be easily stored using JSON, pickle, etc."""
-                return dict(obj)
+
+                return [
+                        [k, v, True]
+                        for k, v in obj.__inherited.iteritems()
+                ] + [
+                        [k, v, False]
+                        for k, v in obj.__local.iteritems()
+                ]
 
         @staticmethod
         def fromstate(state, jd_state=None):
                 """Update the state of this object using previously serialized
                 state obtained via getstate()."""
-                return Facets(init=state)
+
+                rv = Facets()
+                for k, v, inhertited in state:
+                        if not inhertited:
+                                rv[k] = v
+                        else:
+                                rv._set_inherited(k, v)
+                return rv
+
+        def _cmp_priority(self, other):
+                """Compare the facet match priority of two Facets objects.
+                Since the match priority of a Facets object is dependent upon
+                facet sources (local vs parent) and names, we're essentially
+                ensuring that both objects have the same set of facet sources
+                and names."""
+
+                assert type(other) is Facets
+                return cmp(self.__keylist, other.__keylist)
+
+        def _cmp_values(self, other):
+                """Compare the facet values of two Facets objects.  This
+                comparison ignores any masked values."""
+
+                assert type(other) is Facets
+                return dict.__cmp__(self, other)
+
+        def _cmp_all_values(self, other):
+                """Compare all the facet values of two Facets objects.  This
+                comparison takes masked values into account."""
+
+                assert type(other) is Facets
+                rv = cmp(self.__inherited, other.__inherited)
+                if rv == 0:
+                        rv = cmp(self.__local, other.__local)
+                return rv
+
+        def __cmp__(self, other):
+                """Compare two Facets objects.  This comparison takes masked
+                values into account."""
+
+                # check if we're getting compared against something other than
+                # another Factes object.
+                if type(other) is not Facets:
+                        return 1
+
+                # Check for effective facet value changes that could affect
+                # solver computations.
+                rv = self._cmp_values(other)
+                if rv != 0:
+                        return rv
+
+                # Check for facet priority changes that could affect solver
+                # computations.  (Priority changes can occur when local or
+                # inherited facets are added or removed.)
+                rv = self._cmp_priority(other)
+                if rv != 0:
+                        return rv
+
+                # There are no outwardly visible facet priority or value
+                # changes that could affect solver computations, but it's
+                # still possible that we're changing the set of local or
+                # inherited facets in a way that doesn't affect solver
+                # computations.  For example:  we could be adding a local
+                # facet with a value that is masked by an inherited facet, or
+                # having a facet transition from being inherited to being
+                # local without a priority or value change.  Check if this is
+                # the case.
+                rv = self._cmp_all_values(other)
+                return rv
+
+        def __eq__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) == 0)
+
+        def __ne__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) != 0)
+
+        def __ge__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) >= 0)
+
+        def __gt__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) > 0)
+
+        def __le__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) <= 0)
+
+        def __lt__(self, other):
+                """redefine in terms of __cmp__()"""
+                return (Facets.__cmp__(self, other) < 0)
 
         def __repr__(self):
                 s =  "<"
-                s += ", ".join(["%s:%s" % (k, dict.__getitem__(self, k)) for k in self.__keylist])
+                s += ", ".join([
+                    "%s:%s" % (k, dict.__getitem__(self, k))
+                    for k in self.__keylist
+                ])
                 s += ">"
 
                 return s
 
-        def __setitem__(self, item, value):
+        def __keylist_sort(self):
+                """Update __keysort, which is used to determine facet matching
+                order.  Inherited facets always take priority over local
+                facets so make sure all inherited facets come before local
+                facets in __keylist."""
+
+                def facet_sort(x, y):
+                        return len(y) - len(x)
+
+                self.__keylist = []
+                self.__keylist += sorted([
+                        i
+                        for i in self
+                        if i in self.__inherited
+                ], cmp=facet_sort)
+                self.__keylist += sorted([
+                        i
+                        for i in self
+                        if i not in self.__inherited
+                ], cmp=facet_sort)
+
+        def __setitem_internal(self, item, value, inherited=False):
                 if not item.startswith("facet."):
                         raise KeyError, 'key must start with "facet".'
 
                 if not (value == True or value == False):
                         raise ValueError, "value must be boolean"
 
-                if item not in self:
-                        self.__keylist.append(item)
-                        self.__keylist.sort(cmp=lambda x, y: len(y) - len(x))
-                dict.__setitem__(self, item, value)
-                self.__res[item] = re.compile(fnmatch.translate(item))
+                keylist_sort = False
+                if (inherited and item not in self.__inherited) or \
+                    (not inherited and item not in self):
+                        keylist_sort = True
+
+                # save the facet in the local or inherited dictionary
+                # clear the corresponding read-only dictionary
+                if inherited:
+                        self.__inherited[item] = value
+                        self.__inherited_ro = None
+                else:
+                        self.__local[item] = value
+                        self.__local_ro = None
+
+                # Inherited facets always take priority over local facets.
+                if inherited or item not in self.__inherited:
+                        dict.__setitem__(self, item, value)
+                        self.__res[item] = re.compile(fnmatch.translate(item))
 
+                if keylist_sort:
+                        self.__keylist_sort()
 
-        def __getitem__(self, item):
-                """implement facet lookup algorithm here"""
-                # Note that _allow_facet bypasses __getitem__ for performance
-                # reasons; if __getitem__ changes, _allow_facet in _varcet.c
-                # must also be updated.
+        def __setitem__(self, item, value):
+                """__setitem__ only operates on local facets."""
+                self.__setitem_internal(item, value)
+
+        def __getitem_internal(self, item):
+                """Implement facet lookup algorithm here
+
+                Note that _allow_facet bypasses __getitem__ for performance
+                reasons; if __getitem__ changes, _allow_facet in _varcet.c
+                must also be updated.
+
+                We return a tuple of the form (<key>, <value>) where key is
+                the explicitly set facet name (which may be a glob pattern)
+                that matched the caller specific facet name."""
+
                 if not item.startswith("facet."):
                         raise KeyError, "key must start w/ facet."
 
                 if item in self:
-                        return dict.__getitem__(self, item)
+                        return item, dict.__getitem__(self, item)
                 for k in self.__keylist:
                         if self.__res[k].match(item):
-                                return dict.__getitem__(self, k)
+                                return k, dict.__getitem__(self, k)
+
+                return None, True # be inclusive
+
+        def __getitem__(self, item):
+                return self.__getitem_internal(item)[1]
+
+        def __delitem_internal(self, item, inherited=False):
+
+                # check for an attempt to delete an invalid facet
+                if not dict.__contains__(self, item):
+                        raise KeyError, item
+
+                # check for an attempt to delete an invalid local facet
+                if not inherited and item not in self.__local:
+                        raise KeyError, item
+
+                # we should never try to delete an invalid inherited facet
+                assert not inherited or item in self.inherited
 
-                return True # be inclusive
+                keylist_sort = False
+                if inherited and item in self.__local:
+                        # the inherited value was overriding a local value
+                        # that should now be exposed
+                        dict.__setitem__(self, item, self.__local[item])
+                        self.__res[item] = re.compile(fnmatch.translate(item))
+                        keylist_sort = True
+                else:
+                        # delete the item
+                        dict.__delitem__(self, item)
+                        del self.__res[item]
+                        self.__keylist.remove(item)
+
+                # delete item from the local or inherited dictionary
+                # clear the corresponding read-only dictionary
+                if inherited:
+                        rv = self.__inherited[item]
+                        del self.__inherited[item]
+                        self.__inherited_ro = None
+                else:
+                        rv = self.__local[item]
+                        del self.__local[item]
+                        self.__local_ro = None
+
+                if keylist_sort:
+                        self.__keylist_sort()
+                return rv
 
         def __delitem__(self, item):
-                dict.__delitem__(self, item)
-                self.__keylist.remove(item)
-                del self.__res[item]
+                """__delitem__ only operates on local facets."""
+                self.__delitem_internal(item, value)
 
         # allow_action is provided as a native function (see end of class
         # declaration).
 
+        def _set_inherited(self, item, value):
+                """Set an inherited facet."""
+                self.__setitem_internal(item, value, inherited=True)
+
+        def _clear_inherited(self):
+                """Clear all inherited facet."""
+                for k in self.__inherited.keys():
+                        self.__delitem_internal(k, inherited=True)
+
+        def _action_match(self, act):
+                """Find the subset of facet key/values pairs which match any
+                facets present on an action."""
+
+                # find all the facets present in the current action
+                action_facets = frozenset([
+                        a
+                        for a in act.attrs
+                        if a.startswith("facet.")
+                ])
+
+                rv = set()
+                for facet in self.__keylist:
+                        if facet in action_facets:
+                                # we found a matching facet.
+                                rv.add((facet, self[facet]))
+                                continue
+                        for action_facet in action_facets:
+                                if self.__res[facet].match(action_facet):
+                                        # we found a matching facet.
+                                        rv.add((facet, self[facet]))
+                                        break
+
+                return (frozenset(rv))
+
         def pop(self, item, *args, **kwargs):
+                """pop() only operates on local facets."""
+
                 assert len(args) == 0 or (len(args) == 1 and
                     "default" not in kwargs)
-                try:
-                        self.__keylist.remove(item)
-                        del self.__res[item]
-                except ValueError:
-                        if not args and "default" not in kwargs:
-                                raise
-                default = kwargs.get("default", None)
-                if args:
-                        default = args[0]
-                return dict.pop(self, item, default)
+
+                if item not in self.__local:
+                        # check if the user specified a default value
+                        if args:
+                                return args[0]
+                        elif "default" in kwargs:
+                                return kwargs["default"]
+                        if len(self) == 0:
+                                raise KeyError, 'pop(): dictionary is empty'
+                        raise KeyError, item
+
+                return self.__delitem_internal(item, inherited=False)
 
         def popitem(self):
-                popped = dict.popitem(self)
-                self.__keylist.remove(popped[0])
-                del self.__res[popped]
-                return popped
+                """popitem() only operates on local facets."""
+
+                item = None
+                for item, value in self.__local:
+                        break
+
+                if item is None:
+                        raise KeyError, 'popitem(): dictionary is empty'
+
+                self.__delitem_internal(item)
+                return (item, value)
 
         def setdefault(self, item, default=None):
                 if item not in self:
@@ -130,8 +416,16 @@
                 return self[item]
 
         def update(self, d):
-                for k, v in d.iteritems():
-                        self[k] = v
+                if type(d) == Facets:
+                        # preserve inherited facets.
+                        for k, v in d.__inherited.iteritems():
+                                self._set_inherited(k, v)
+                        for k, v in d.__local.iteritems():
+                                self[k] = v
+                        return
+
+                for k in d:
+                        self[k] = d[k]
 
         def keys(self):
                 return self.__keylist[:]
@@ -139,6 +433,29 @@
         def values(self):
                 return [self[k] for k in self.__keylist]
 
+        def _src_values(self, name):
+                """A facet may be set via multiple sources and hence have
+                multiple values.  If there are multiple values for a facet,
+                all but one of those values will be masked.  So for a given
+                facet, return a list of tuples of the form (<value>, <src>,
+                <masked>) which represent all currently set values for this
+                facet."""
+
+                rv = []
+                if name in self.__inherited:
+                        src = self.FACET_SRC_PARENT
+                        value = self.__inherited[name]
+                        masked = False
+                        rv.append((value, src, masked))
+                if name in self.__local:
+                        src = self.FACET_SRC_LOCAL
+                        value = self.__local[name]
+                        masked = False
+                        if name in self.__inherited:
+                                masked = True
+                        rv.append((value, src, masked))
+                return rv
+
         def items(self):
                 return [a for a in self.iteritems()]
 
@@ -151,7 +468,38 @@
 
         def clear(self):
                 self.__keylist = []
-                self.__res = []
+                self.__res = {}
+                self.__local = {}
+                self.__local_ro = None
+                self.__inherited = {}
+                self.__inherited_ro = None
                 dict.clear(self)
 
+        def _match_src(self, name):
+                """Report the source of a facet value if we were to attempt to
+                look it up in the current Facets object dictionary."""
+
+                k = self.__getitem_internal(name)[0]
+                if k in self.__inherited:
+                        return self.FACET_SRC_PARENT
+                if k in self.__local:
+                        return self.FACET_SRC_LOCAL
+                assert k is None and k not in self
+                return self.FACET_SRC_SYSTEM
+
+        # For convenience, provide callers with direct access to local and
+        # parent facets via cached read-only dictionaries.
+        @property
+        def local(self):
+                if self.__local_ro is None:
+                        self.__local_ro = ImmutableDict(self.__local)
+                return self.__local_ro
+
+        @property
+        def inherited(self):
+                if self.__inherited_ro is None:
+                        self.__inherited_ro = ImmutableDict(self.__inherited)
+                return self.__inherited_ro
+
+
 Facets.allow_action = types.MethodType(_allow_facet, None, Facets)
--- a/src/modules/flavor/base.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/flavor/base.py	Wed Aug 14 11:12:35 2013 +0530
@@ -53,9 +53,11 @@
                 if not self.dirs:
                         return _("Couldn't find '%s'") % self.file_path
                 else:
-                        return _("Couldn't find '%s' in any of the specified "
-                            "search directories:\n%s") % (self.file_path,
-                            "\n".join(["\t" + d for d in sorted(self.dirs)]))
+                        return _("Couldn't find '%(path)s' in any of the "
+                            "specified search directories:\n%(dirs)s") % \
+                            {"path": self.file_path,
+                            "dirs": "\n".join(
+                            ["\t" + d for d in sorted(self.dirs)])}
 
 class MultipleDefaultRunpaths(DependencyAnalysisError):
         """Exception that is raised when multiple $PGKDEPEND_RUNPATH tokens
--- a/src/modules/flavor/elf.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/flavor/elf.py	Wed Aug 14 11:12:35 2013 +0530
@@ -42,7 +42,8 @@
                 self.ex = ex
 
         def __str__(self):
-                return _("%s had this elf error:%s") % (self.fp, self.ex)
+                return _("%(file)s had this elf error:%(err)s") % \
+                    {"file": "self.fp", "err": self.ex}
 
 class UnsupportedDynamicToken(base.DependencyAnalysisError):
         """Exception that is used for elf dependencies which have a dynamic
--- a/src/modules/fmri.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/fmri.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import fnmatch
@@ -317,7 +317,7 @@
                         pkg_str = "pkg://"
                 return "%s%s/%s" % (pkg_str, self.publisher, self.pkg_name)
 
-        def get_short_fmri(self, default_publisher = None):
+        def get_short_fmri(self, default_publisher=None, anarchy=False):
                 """Return a string representation of the FMRI without a specific
                 version."""
                 publisher = self.publisher
@@ -329,7 +329,8 @@
                 else:
                         version = "@" + self.version.get_short_version()
 
-                if not publisher or publisher.startswith(PREF_PUB_PFX):
+                if not publisher or publisher.startswith(PREF_PUB_PFX) \
+                    or anarchy:
                         return "pkg:/%s%s" % (self.pkg_name, version)
 
                 return "pkg://%s/%s%s" % (publisher, self.pkg_name, version)
--- a/src/modules/gui/beadmin.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/beadmin.py	Wed Aug 14 11:12:35 2013 +0530
@@ -391,8 +391,10 @@
                                 msg += _("<b>Couldn't rename Boot "
                                     "Environments:</b>\n")
                                 for orig in not_renamed:
-                                        msg += _("%s <b>to</b> %s\n") % (orig, \
-                                            not_renamed.get(orig))
+                                        msg += _("%(src)s <b>to</b> "
+                                            "%(targ)s\n") % \
+                                            {"src": orig,
+                                            "targ": not_renamed.get(orig)}
                         gobject.idle_add(self.__error_occurred, msg)
                         return
                 gobject.idle_add(self.__on_cancel_be_clicked, None)
--- a/src/modules/gui/installupdate.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/installupdate.py	Wed Aug 14 11:12:35 2013 +0530
@@ -564,8 +564,11 @@
 
         def __on_confirm_cancel_button_clicked(self, widget):
                 self.w_confirm_dialog.hide()
-                if self.top_level and widget: # User clicked cacnel, widget != None
-                        gobject.idle_add(self.parent.install_terminated)
+                if widget: # User clicked cancel, widget != None
+                     if self.top_level:
+                         gobject.idle_add(self.parent.install_terminated)
+                     else:
+                         self.w_dialog.hide()
 
         def __on_createplandialog_delete(self, widget, event):
                 self.__on_cancelcreateplan_clicked(None)
@@ -1029,10 +1032,8 @@
                 self.w_confirm_ok_button.grab_focus()
                 self.__start_substage(None,
                             bounce_progress=False)
-                if self.top_level:
+                if not self.top_level:
                         self.__reset_window_title()
-                else:
-                        self.w_dialog.hide()
                 self.w_confirm_dialog.show()
 
 
--- a/src/modules/gui/misc.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/misc.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 SPECIAL_CATEGORIES = ["locale", "plugin"] # We should cut all, but last part of the
@@ -61,12 +61,11 @@
 from pkg.gui.misc_non_gui import get_version as g_version
 from pkg.gui.misc_non_gui import get_os_version_and_build as g_os_version_and_build
 
-from pkg.gui.misc_non_gui import get_log_dir as ge_log_dir
+from pkg.gui.misc_non_gui import get_log_path as ge_log_path
 from pkg.gui.misc_non_gui import get_log_error_ext as ge_log_error_ext
 from pkg.gui.misc_non_gui import get_log_info_ext as ge_log_info_ext
 from pkg.gui.misc_non_gui import get_catalogrefresh_exception_msg as get_msg
 from pkg.gui.misc_non_gui import get_um_name as get_um
-from pkg.gui.misc_non_gui import get_image_path as g_image_path
 from pkg.gui.misc_non_gui import is_frameworkerror as is_frameworke
 
 from pkg.client import global_settings
@@ -187,9 +186,6 @@
                     gtk.MESSAGE_INFO)
                 return False
         return True
-
-def get_image_path():
-        return g_image_path()
                 
 def get_version():
         return g_version()
@@ -228,8 +224,8 @@
                 pass
         return publisher_str
 
-def get_log_dir():
-        return ge_log_dir()
+def get_log_path(client_name):
+        return ge_log_path(client_name)
 
 def get_log_error_ext():
         return ge_log_error_ext()
@@ -400,8 +396,10 @@
         try:
                 api_o = ngao(img_dir, progtrack)
         except api_errors.VersionException, ex:
-                message = _("Version mismatch: expected version %d, got version %d") % \
-                    (ex.expected_version, ex.received_version)
+                message = _("Version mismatch: expected version %(expected)d, "
+                    "got version %(found)d") % \
+                    {"expected": ex.expected_version,
+                    "found": ex.received_version}
         except api_errors.ImageNotFoundException, ex:
                 message = _("%s is not an install image") % ex.user_dir
         except api_errors.ImageLockedError, ex:
--- a/src/modules/gui/misc_non_gui.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/misc_non_gui.py	Wed Aug 14 11:12:35 2013 +0530
@@ -41,27 +41,11 @@
 
 # The current version of the Client API the PM, UM and
 # WebInstall GUIs have been tested against and are known to work with.
-CLIENT_API_VERSION = 73
+CLIENT_API_VERSION = 75
 LOG_DIR = "/var/tmp"
 LOG_ERROR_EXT = "_error.log"
 LOG_INFO_EXT = "_info.log"
 PKG_CLIENT_NAME_UM = "updatemanager"
-IMAGE_DIRECTORY_DEFAULT = "/"   # Image default directory
-IMAGE_DIR_COMMAND = "svcprop -p update/image_dir svc:/application/pkg/update"
-
-
-def get_image_path():
-        try:
-                image_directory = os.environ["PKG_IMAGE"]
-        except KeyError:
-                image_directory = \
-                    os.popen(IMAGE_DIR_COMMAND).readline().rstrip()
-                if len(image_directory) == 0:
-                        image_directory = IMAGE_DIRECTORY_DEFAULT
-        return image_directory
-
-def get_log_dir():
-        return LOG_DIR
 
 def get_log_error_ext():
         return LOG_ERROR_EXT
@@ -87,11 +71,18 @@
                 os_ver += " (" + platform.uname()[3] + ")"
         return os_ver
 
+def get_log_path(client_name):
+        if portable.is_admin():
+                log_path = os.path.join(LOG_DIR, client_name)
+        else:
+                user_name = portable.get_username()
+                log_path = os.path.join(LOG_DIR, client_name + "_" + user_name)
+        return log_path
+
 def setup_logging(client_name):
         normal_setup = True
-        log_path = os.path.join(LOG_DIR, client_name)
         err_str = ""
-
+        log_path = get_log_path(client_name)
         infolog_path = log_path + LOG_INFO_EXT
         try:
                 info_h = logging.handlers.RotatingFileHandler(infolog_path,
--- a/src/modules/gui/pmlogging.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/pmlogging.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import sys
@@ -85,19 +85,18 @@
                 self.w_view_log_dialog.hide()
 
         def __on_log_clear_button_clicked(self, widget):
-                log_dir = gui_misc.get_log_dir()
                 ext = gui_misc.get_log_error_ext()
-                self.__clear_logs(log_dir, ext) 
+                self.__clear_logs(ext) 
                 ext = gui_misc.get_log_info_ext()
-                self.__clear_logs(log_dir, ext) 
+                self.__clear_logs(ext) 
                 gui_misc.shutdown_logging()
                 gui_misc.setup_logging()
                 self.log_activate()
 
-        def __clear_logs(self, log_dir, ext):
-                self.__clear_log(os.path.join(log_dir, gui_misc.get_pm_name() + ext))
-                self.__clear_log(os.path.join(log_dir, gui_misc.get_wi_name() + ext))
-                self.__clear_log(os.path.join(log_dir, gui_misc.get_um_name() + ext))
+        def __clear_logs(self, ext):
+                self.__clear_log(gui_misc.get_log_path(gui_misc.get_pm_name()) + ext)
+                self.__clear_log(gui_misc.get_log_path(gui_misc.get_wi_name()) + ext)
+                self.__clear_log(gui_misc.get_log_path(gui_misc.get_um_name()) + ext)
 
         @staticmethod
         def __clear_log(path):
@@ -137,11 +136,10 @@
                 textbuffer = self.w_log_errors_textview.get_buffer()
                 textbuffer.set_text("")
                 textiter = textbuffer.get_end_iter()
-                log_dir = gui_misc.get_log_dir()
                 log_err_ext = gui_misc.get_log_error_ext()
-                pm_err_log = os.path.join(log_dir, gui_misc.get_pm_name() + log_err_ext)
-                wi_err_log = os.path.join(log_dir, gui_misc.get_wi_name() + log_err_ext)
-                um_err_log = os.path.join(log_dir, gui_misc.get_um_name() + log_err_ext)
+                pm_err_log = gui_misc.get_log_path(gui_misc.get_pm_name()) + log_err_ext
+                wi_err_log = gui_misc.get_log_path(gui_misc.get_wi_name()) + log_err_ext
+                um_err_log = gui_misc.get_log_path(gui_misc.get_um_name()) + log_err_ext
 
                 self.__write_to_view_log(um_err_log,
                     textbuffer, textiter, _("None: ") + gui_misc.get_um_name() + "\n")
@@ -156,11 +154,10 @@
                 textbuffer = self.w_log_info_textview.get_buffer()
                 textbuffer.set_text("")
                 textiter = textbuffer.get_end_iter()
-                log_dir = gui_misc.get_log_dir()
                 log_info_ext = gui_misc.get_log_info_ext()
-                pm_info_log = os.path.join(log_dir, gui_misc.get_pm_name() + log_info_ext)
-                wi_info_log = os.path.join(log_dir, gui_misc.get_wi_name() + log_info_ext)
-                um_info_log = os.path.join(log_dir, gui_misc.get_um_name() + log_info_ext)
+                pm_info_log = gui_misc.get_log_path(gui_misc.get_pm_name()) + log_info_ext
+                wi_info_log = gui_misc.get_log_path(gui_misc.get_wi_name()) + log_info_ext
+                um_info_log = gui_misc.get_log_path(gui_misc.get_um_name()) + log_info_ext
 
                 self.__write_to_view_log(um_info_log,
                     textbuffer, textiter, _("None: ") + gui_misc.get_um_name() + "\n")
--- a/src/modules/gui/preferences.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/preferences.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import g11nsvc as g11nsvc
@@ -32,7 +32,7 @@
         import pygtk
         pygtk.require("2.0")
 except ImportError:
-        sys.exit(1)        
+        sys.exit(1)
 import pkg.client.api_errors as api_errors
 import pkg.client.api as api
 import pkg.gui.misc as gui_misc
@@ -536,16 +536,15 @@
                                 break
                         facets = None
                         if manifest != None:
-                                manifest.gen_actions(())
-                                facets = manifest.facets
+                                facets = list(manifest.gen_facets())
                         if debug and facets != None:
                                 print "DEBUG facets from system/locale:", facets
 
                         facetlocales = []
                         if facets == None:
                                 return facetlocales
-                        
-                        for facet_key in facets.keys():
+
+                        for facet_key in facets:
                                 if not facet_key.startswith(LOCALE_PREFIX):
                                         continue
                                 m = re.match(LOCALE_MATCH, facet_key)
@@ -629,7 +628,7 @@
                         selected = row[enumerations.LOCALE_SELECTED]
                         locale = row[enumerations.LOCALE]
                         lang = locale.split("_")[0]
-                        
+
                         if not lang_locale_dict.has_key(lang):
                                 lang_locale_dict[lang] = {}
                         lang_locale_dict[lang][locale] = selected
@@ -766,7 +765,7 @@
 
         def __on_preferencescancel_clicked(self, widget):
                 self.w_preferencesdialog.hide()
-                
+
         def __on_preferencesclose_clicked(self, widget):
                 error_dialog_title = _("Preferences")
                 text = self.w_gsig_name_entry.get_text()
--- a/src/modules/gui/progress.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/progress.py	Wed Aug 14 11:12:35 2013 +0530
@@ -142,9 +142,10 @@
                 self.display_download_info()
                 if "startpkg" in outspec.changed:
                         self.update_details_text(
-                            _("Package %d of %d: %s\n") % (
-                            self.dl_pkgs.items + 1,
-                            self.dl_pkgs.goalitems, self.dl_pkgs.curinfo),
+                            _("Package %(num)d of %(goal)d: %(info)s\n") % {
+                            "num": self.dl_pkgs.items + 1,
+                            "goal": self.dl_pkgs.goalitems,
+                            "info": self.dl_pkgs.curinfo},
                             "level1")
 
                 if outspec.last:
@@ -223,9 +224,11 @@
                 i = "level1" if self.indent else ""
 
                 running = " ".join([str(s) for s in self.linked_running])
-                msg = _("Linked images: %s done; %d working: %s\n") % \
-                    (progress.format_pair("%d", done, self.linked_total),
-                    len(self.linked_running), running)
+                msg = _("Linked images: %(num)s done; %(numworking)d working: "
+                    "%(running)s\n") % \
+                    {"num": progress.format_pair("%d", done, self.linked_total),
+                    "numworking": len(self.linked_running),
+                    "running": running}
                 self.update_details_text(msg, i)
 
         def _li_recurse_progress_output(self, lin):
--- a/src/modules/gui/uarenamebe.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/gui/uarenamebe.py	Wed Aug 14 11:12:35 2013 +0530
@@ -220,8 +220,9 @@
         def __g_be_rename_problem_dialog(new_name, orig_name):
                 msg_type = gtk.MESSAGE_INFO
                 error_msg = _("Could not change the BE name to:\n\t"
-                    "%s\n\nThe following name will be used instead:"
-                    "\n\t%s" % (new_name, orig_name))
+                    "%(targ)s\n\nThe following name will be used instead:"
+                    "\n\t%(instead)s") % \
+                    {"targ": new_name, "instead": orig_name}
                 msg_title = _("BE Name")
                 gui_misc.error_occurred(None, error_msg, msg_title, msg_type)
 
--- a/src/modules/lint/engine.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/lint/engine.py	Wed Aug 14 11:12:35 2013 +0530
@@ -40,7 +40,7 @@
 import urllib2
 
 PKG_CLIENT_NAME = "pkglint"
-CLIENT_API_VERSION = 73
+CLIENT_API_VERSION = 75
 pkg.client.global_settings.client_name = PKG_CLIENT_NAME
 
 class LintEngineException(Exception):
@@ -678,7 +678,7 @@
         EXACT = 0
         LATEST_SUCCESSOR = 1
 
-        def get_manifest(self, pkg_name, search_type=EXACT):
+        def get_manifest(self, pkg_name, search_type=EXACT, reference=False):
                 """Returns the first available manifest for a given package
                 name, searching hierarchically in the lint manifests,
                 the lint_repo or the ref_repo for that single package.
@@ -689,6 +689,10 @@
                 When search_type is LintEngine.LATEST_SUCCESSOR, we return the
                 most recent successor of the provided package, using the
                 lint_fmri_successor() method defined in this module.
+
+                If 'reference' is True, only search for the package using the
+                reference image. If no reference image has been configured, this
+                raises a pkg.lint.base.LintException.
                 """
 
                 if not pkg_name.startswith("pkg:/"):
@@ -790,8 +794,16 @@
                                 return mf
 
                 # search hierarchically for the given package name in our
-                # local manifests, our lint image, or our reference image
-                # and return a manifest for that package.
+                # local manifests, using our lint image, or using our reference
+                # image and return a manifest for that package.
+                if reference:
+                     if not self.ref_api_inst:
+                             raise base.LintException(
+                                _("No reference repository has been "
+                                "configured"))
+                     return mf_from_image(self.ref_api_inst, pkg_name,
+                        search_type)
+
                 for mf in self.lint_manifests:
                         search_fmri = build_fmri(pkg_name)
                         if search_type == self.LATEST_SUCCESSOR and \
--- a/src/modules/lint/pkglint_action.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/lint/pkglint_action.py	Wed Aug 14 11:12:35 2013 +0530
@@ -1485,3 +1485,25 @@
                             msgid="%s%s.3" % (self.name, pkglint_id))
 
         username_format.pkglint_desc = _("User names should be valid.")
+
+        def version_incorporate(self, action, manifest, engine,
+            pkglint_id="011"):
+                """Checks that 'incorporate' dependencies have a version."""
+
+                if action.name != "depend":
+                        return
+                if action.attrs.get("type") != "incorporate":
+                        return
+
+                fmri = action.attrs["fmri"]
+                pfmri = pkg.fmri.PkgFmri(fmri, build_release="5.11")
+                if not pfmri.version:
+                        engine.error(
+                            _("'incorporate' depend action on %(fmri)s in "
+                            "%(pkg)s does not have a version.") %
+                            {"fmri": fmri,
+                            "pkg": manifest.fmri},
+                            msgid="%s%s" % (self.name, pkglint_id))
+
+        version_incorporate.pkglint_desc = _("'incorporate' dependencies should"
+            " have a version.")
--- a/src/modules/manifest.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/manifest.py	Wed Aug 14 11:12:35 2013 +0530
@@ -29,11 +29,12 @@
 import hashlib
 import os
 import tempfile
-from itertools import groupby, chain, repeat, izip
+from itertools import groupby, chain, product, repeat, izip
 from operator import itemgetter
 
 import pkg.actions as actions
 import pkg.client.api_errors as apx
+import pkg.facet as facet
 import pkg.misc as misc
 import pkg.portable as portable
 import pkg.variant as variant
@@ -123,8 +124,7 @@
                 self.fmri = pfmri
 
                 self._cache = {}
-                self._facets = None     # facets seen in package
-                self._variants = None   # variants seen in package
+                self._absent_cache = []
                 self.actions = []
                 self.actions_bytype = {}
                 self.attributes = {} # package-wide attributes
@@ -177,16 +177,28 @@
                         """handle key values that may be lists"""
                         if type(v) is not list:
                                 return v
-                        return frozenset(v)
+                        return tuple(v)
 
-                sdict = dict(
-                    ((a.name, hashify(a.attrs.get(a.key_attr, id(a)))), a)
-                    for a in self.gen_actions(self_exclude)
-                )
-                odict = dict(
-                    ((a.name, hashify(a.attrs.get(a.key_attr, id(a)))), a)
-                    for a in origin.gen_actions(origin_exclude)
-                )
+                def dictify(mf, excludes):
+                        # Transform list of actions into a dictionary keyed by
+                        # action key attribute, key attribute and mediator, or
+                        # id if there is no key attribute.
+                        for a in mf.gen_actions(excludes):
+                                if (a.name == "link" or
+                                    a.name == "hardlink") and \
+                                    a.attrs.get("mediator"):
+                                        akey = (a.name, tuple([
+                                            a.attrs[a.key_attr],
+                                            a.attrs.get("mediator-version"),
+                                            a.attrs.get("mediator-implementation")
+                                        ]))
+                                else:
+                                        akey = (a.name, hashify(a.attrs.get(
+                                            a.key_attr, id(a))))
+                                yield (akey, a)
+
+                sdict = dict(dictify(self, self_exclude))
+                odict = dict(dictify(origin, origin_exclude))
 
                 sset = set(sdict.iterkeys())
                 oset = set(odict.iterkeys())
@@ -342,7 +354,7 @@
                         }
                         for mvariant in mvariants:
                                 a = "set name=pkg.mediator " \
-                                    "value=%s %s %s\n".rstrip() % (mediation[0],
+                                    "value=%s %s %s\n" % (mediation[0],
                                      " ".join((
                                          "=".join(t)
                                           for t in values.iteritems()
@@ -355,13 +367,267 @@
                                 )
                                 yield a
 
+        def _gen_attrs_to_str(self):
+                """Generate set action supplemental data containing all facets
+                and variants from self.actions and size information.  Each
+                returned line must be newline-terminated."""
+
+                emit_variants = "pkg.variant" not in self
+                emit_facets = "pkg.facet" not in self
+                emit_sizes = "pkg.size" not in self and "pkg.csize" not in self
+
+                if not any((emit_variants, emit_facets, emit_sizes)):
+                        # Package already has these attributes.
+                        return
+
+                # List of possible variants and possible values for them.
+                variants = defaultdict(set)
+
+                # Seed with declared set of variants as actions may be common to
+                # both and so will not be tagged with variant.
+                for name in self.attributes:
+                        if name[:8] == "variant.":
+                                variants[name] = set(self.attributes[name])
+
+                # List of possible facets and under what variant combinations
+                # they were seen.
+                facets = defaultdict(set)
+
+                # Unique (facet, value) (variant, value) combinations.
+                refs = defaultdict(lambda: defaultdict(int))
+
+                for a in self.gen_actions():
+                        name = a.name
+                        attrs = a.attrs
+                        if name == "set":
+                                if attrs["name"][:12] == "pkg.variant":
+                                        emit_variants = False
+                                elif attrs["name"][:9] == "pkg.facet":
+                                        emit_facets = False
+
+                        afacets = []
+                        avariants = []
+                        for attr, val in attrs.iteritems():
+                                if attr[:8] == "variant.":
+                                        variants[attr].add(val)
+                                        avariants.append((attr, val))
+                                elif attr[:6] == "facet.":
+                                        afacets.append((attr, val))
+
+                        for name, val in afacets:
+                                # Facet applicable to this particular variant
+                                # combination.
+                                varkey = tuple(sorted(avariants))
+                                facets[varkey].add(name)
+
+                        # This *must* be sorted to ensure reproducible set
+                        # action generation for sizes and to ensure each
+                        # combination is actually unique.
+                        varcetkeys = tuple(sorted(chain(afacets, avariants)))
+                        refs[varcetkeys]["csize"] += misc.get_pkg_otw_size(a)
+                        if name == "signature":
+                                refs[varcetkeys]["csize"] += \
+                                    a.get_action_chain_csize()
+                        refs[varcetkeys]["size"] += a.get_size()
+
+                # Prevent scope leak.
+                afacets = avariants = attrs = varcetkeys = None
+
+                if emit_variants:
+                        # Unnecessary if we can guarantee all variants will be
+                        # declared at package level.  Omit the "variant." prefix
+                        # from attribute values since that's implicit and can be
+                        # added back when the action is parsed.
+                        yield "%s\n" % AttributeAction(None, name="pkg.variant",
+                            value=sorted(v[8:] for v in variants))
+
+                # Emit a set action for every variant used with possible values
+                # if one does not already exist.
+                for name in variants:
+                        # merge_facets needs the variant values sorted and this
+                        # is desirable when generating the variant attr anyway.
+                        variants[name] = sorted(variants[name])
+                        if name not in self.attributes:
+                                yield "%s\n" % AttributeAction(None, name=name,
+                                    value=variants[name])
+
+                if emit_facets:
+                        # Get unvarianted facet set.
+                        cfacets = facets.pop((), set())
+
+                        # For each variant combination, remove unvarianted
+                        # facets since they are common to all variants.
+                        for varkey, fnames in facets.items():
+                                fnames.difference_update(cfacets)
+                                if not fnames:
+                                        # No facets unique to this combo;
+                                        # discard.
+                                        del facets[varkey]
+
+                        # If all possible variant combinations supported by the
+                        # package have at least one facet, then the intersection
+                        # of facets for all variants can be merged with the
+                        # common set.
+                        merge_facets = len(facets) > 0
+                        if merge_facets:
+                                # Determine unique set of variant combinations
+                                # seen for faceted actions.
+                                vcombos = set((
+                                    tuple(
+                                        vpair[0]
+                                        for vpair in varkey
+                                    )
+                                    for varkey in facets
+                                ))
+
+                                # For each unique variant combination, determine
+                                # if the cartesian product of all variant values
+                                # supported by the package for the combination
+                                # has been seen.  In other words, if the
+                                # combination is ((variant.arch,)) and the
+                                # package supports (i386, sparc), then both
+                                # (variant.arch, i386) and (variant.arch, sparc)
+                                # must exist.  This code assumes variant values
+                                # for each variant are already sorted.
+                                for pair in chain.from_iterable(
+                                    product(*(
+                                        tuple((name, val)
+                                            for val in variants[name])
+                                        for name in vcombo)
+                                    )
+                                    for vcombo in vcombos
+                                ):
+                                        if pair not in facets:
+                                                # If any combination the package
+                                                # supports has not been seen for
+                                                # one or more facets, then some
+                                                # facets are unique to one or
+                                                # more combinations.
+                                                merge_facets = False
+                                                break
+
+                        if merge_facets:
+                                # Merge the facets common to all variants if safe;
+                                # if we always merged them, then facets only
+                                # used by a single variant (think i386-only or
+                                # sparc-only content) would be seen unvarianted
+                                # (that's bad).
+                                vfacets = facets.values()
+                                vcfacets = vfacets[0].intersection(*vfacets[1:])
+
+                                if vcfacets:
+                                        # At least one facet is shared between
+                                        # all variant combinations; move the
+                                        # common ones to the unvarianted set.
+                                        cfacets.update(vcfacets)
+
+                                        # Remove facets common to all combos.
+                                        for varkey, fnames in facets.items():
+                                                fnames.difference_update(vcfacets)
+                                                if not fnames:
+                                                        # No facets unique to
+                                                        # this combo; discard.
+                                                        del facets[varkey]
+
+                        # Omit the "facet." prefix from attribute values since
+                        # that's implicit and can be added back when the action
+                        # is parsed.
+                        val = sorted(f[6:] for f in cfacets)
+                        if not val:
+                                # If we don't do this, action stringify will
+                                # emit this as "set name=pkg.facet" which is
+                                # then transformed to "set name=name
+                                # value=pkg.facet".  Not what we wanted, but is
+                                # expected for historical reasons.
+                                val = ""
+
+                        # Always emit an action enumerating the list of facets
+                        # common to all variants, even if there aren't any.
+                        # That way if there are also no variant-specific facets,
+                        # package operations will know that no facets are used
+                        # by the package instead of having to scan the whole
+                        # manifest.
+                        yield "%s\n" % AttributeAction(None,
+                            name="pkg.facet.common", value=val)
+
+                        # Now emit a pkg.facet action for each variant
+                        # combination containing the list of facets unique to
+                        # that combination.
+                        for varkey, fnames in facets.iteritems():
+                                # A unique key for each combination is needed,
+                                # and using a hash obfuscates that interface
+                                # while giving us a reliable way to generate
+                                # a reproducible, unique identifier.  The key
+                                # string below looks like this before hashing:
+                                #     variant.archi386variant.debug.osnetTrue...
+                                key = hashlib.sha1(
+                                    "".join("%s%s" % v for v in varkey)
+                                ).hexdigest()
+
+                                # Omit the "facet." prefix from attribute values
+                                # since that's implicit and can be added back
+                                # when the action is parsed.
+                                act = AttributeAction(None,
+                                    name="pkg.facet.%s" % key,
+                                    value=sorted(f[6:] for f in fnames))
+                                attrs = act.attrs
+                                # Tag action with variants.
+                                for v in varkey:
+                                        attrs[v[0]] = v[1]
+                                yield "%s\n" % act
+
+                # Emit pkg.[c]size attribute for [compressed] size of package
+                # for each facet/variant combination.
+                csize = 0
+                size = 0
+                for varcetkeys in refs:
+                        rcsize = refs[varcetkeys]["csize"]
+                        rsize = refs[varcetkeys]["size"]
+
+                        if not varcetkeys:
+                                # For unfaceted/unvarianted actions, keep a
+                                # running total so a single [c]size action can
+                                # be generated.
+                                csize += rcsize
+                                size += rsize
+                                continue
+
+                        if emit_sizes and (rcsize > 0 or rsize > 0):
+                                # Only emit if > 0; actions may be
+                                # faceted/variant without payload.
+
+                                # A unique key for each combination is needed,
+                                # and using a hash obfuscates that interface
+                                # while giving us a reliable way to generate
+                                # a reproducible, unique identifier.  The key
+                                # string below looks like this before hashing:
+                                #     facet.docTruevariant.archi386...
+                                key = hashlib.sha1(
+                                    "".join("%s%s" % v for v in varcetkeys)
+                                ).hexdigest()
+
+                                # The sizes are abbreviated in the name of byte
+                                # conservation.
+                                act = AttributeAction(None,
+                                    name="pkg.sizes.%s" % key,
+                                    value=["csz=%s" % rcsize, "sz=%s" % rsize])
+                                attrs = act.attrs
+                                for v in varcetkeys:
+                                        attrs[v[0]] = v[1]
+                                yield "%s\n" % act
+
+                if emit_sizes:
+                        act = AttributeAction(None, name="pkg.sizes.common",
+                            value=["csz=%s" % csize, "sz=%s" % size])
+                        yield "%s\n" % act
+
         def _actions_to_dict(self, references):
                 """create dictionary of all actions referenced explicitly or
                 implicitly from self.actions... include variants as values;
                 collapse variants where possible"""
 
                 refs = {}
-                # build a dictionary containing all directories tagged w/
+                # build a dictionary containing all actions tagged w/
                 # variants
                 for a in self.actions:
                         v, f = a.get_varcet_keys()
@@ -407,6 +673,117 @@
 
                 return list(s)
 
+        def gen_facets(self, excludes=EmptyI, patterns=EmptyI):
+                """A generator function that returns the supported facet
+                attributes (strings) for this package based on the specified (or
+                current) excludes that also match at least one of the patterns
+                provided.  Facets must be true or false so a list of possible
+                facet values is not returned."""
+
+                if self.excludes == excludes:
+                        excludes = EmptyI
+                assert excludes == EmptyI or self.excludes == EmptyI
+
+                try:
+                        facets = self["pkg.facet"]
+                except KeyError:
+                        facets = None
+
+                if facets is not None and excludes == EmptyI:
+                        # No excludes? Then use the pre-determined set of
+                        # facets.
+                        for f in misc.yield_matching("facet.", facets, patterns):
+                                yield f
+                        return
+
+                # If different excludes were specified, then look for pkg.facet
+                # actions containing the list of facets.
+                found = False
+                seen = set()
+                for a in self.gen_actions_by_type("set", excludes=excludes):
+                        if a.attrs["name"][:10] == "pkg.facet.":
+                                # Either a pkg.facet.common action or a
+                                # pkg.facet.X variant-specific action.
+                                found = True
+                                val = a.attrlist("value")
+                                if len(val) == 1 and val[0] == "":
+                                        # No facets.
+                                        continue
+
+                                for f in misc.yield_matching("facet.", (
+                                    "facet.%s" % n
+                                    for n in val
+                                ), patterns):
+                                        if f in seen:
+                                                # Prevent duplicates; it's
+                                                # possible a given facet may be
+                                                # valid for more than one unique
+                                                # variant combination that's
+                                                # allowed by current excludes.
+                                                continue
+
+                                        seen.add(f)
+                                        yield f
+
+                if not found:
+                        # Fallback to sifting actions to yield possible.
+                        facets = self._get_varcets(excludes=excludes)[1]
+                        for f in misc.yield_matching("facet.", facets, patterns):
+                                yield f
+
+        def gen_variants(self, excludes=EmptyI, patterns=EmptyI):
+                """A generator function that yields a list of tuples of the form
+                (variant, [values]).  Where 'variant' is the variant attribute
+                name (e.g. 'variant.arch') and '[values]' is a list of the
+                variant values supported by this package.  Variants returned are
+                those allowed by the specified (or current) excludes that also
+                match at least one of the patterns provided."""
+
+                if self.excludes == excludes:
+                        excludes = EmptyI
+                assert excludes == EmptyI or self.excludes == EmptyI
+
+                try:
+                        variants = self["pkg.variant"]
+                except KeyError:
+                        variants = None
+
+                if variants is not None and excludes == EmptyI:
+                        # No excludes? Then use the pre-determined set of
+                        # variants.
+                        for v in misc.yield_matching("variant.", variants,
+                            patterns):
+                                yield v, self.attributes.get(v, [])
+                        return
+
+                # If different excludes were specified, then look for
+                # pkg.variant action containing the list of variants.
+                found = False
+                variants = defaultdict(set)
+                for a in self.gen_actions_by_type("set", excludes=excludes):
+                        aname = a.attrs["name"]
+                        if aname == "pkg.variant":
+                                val = a.attrlist("value")
+                                if len(val) == 1 and val[0] == "":
+                                        # No variants.
+                                        return
+                                for v in val:
+                                        found = True
+                                        # Ensure variant entries exist (debug
+                                        # variants may not) via defaultdict.
+                                        variants["variant.%s" % v]
+                        elif aname[:8] == "variant.":
+                                for v in a.attrlist("value"):
+                                        found = True
+                                        variants[aname].add(v)
+
+                if not found:
+                        # Fallback to sifting actions to get possible.
+                        variants = self._get_varcets(excludes=excludes)[0]
+
+                for v in misc.yield_matching("variant.", variants, patterns):
+                        yield v, variants[v]
+
         def gen_mediators(self, excludes=EmptyI):
                 """A generator function that yields tuples of the form (mediator,
                 mediations) expressing the set of possible mediations for this
@@ -580,10 +957,9 @@
 
                 self.actions = []
                 self.actions_bytype = {}
-                self._variants = None
-                self._facets = None
                 self.attributes = {}
                 self._cache = {}
+                self._absent_cache = []
 
                 # So we could build up here the type/key_attr dictionaries like
                 # sdict and odict in difference() above, and have that be our
@@ -649,12 +1025,6 @@
                 if excludes and not action.include_this(excludes):
                         return
 
-                if self._variants:
-                        # Reset facet/variant cache if needed (if one is set,
-                        # then both are set, so only need to check for one).
-                        self._facets = None
-                        self._variants = None
-
                 self.actions.append(action)
                 try:
                         self.actions_bytype[aname].append(action)
@@ -669,14 +1039,66 @@
                 """Fill attribute array w/ set action contents."""
                 try:
                         keyvalue = action.attrs["name"]
-                        if keyvalue == "fmri":
-                                keyvalue = "pkg.fmri"
-                        if keyvalue not in self.attributes:
-                                self.attributes[keyvalue] = \
-                                    action.attrs["value"]
-                except KeyError: # ignore broken set actions
+                        if keyvalue[:10] == "pkg.sizes.":
+                                # To reduce manifest bloat, size and csize
+                                # are set on a single action so need splitting
+                                # into separate attributes.
+                                attrval = action.attrlist("value")
+                                for entry in attrval:
+                                        szname, szval = entry.split("=", 1)
+                                        if szname == "sz":
+                                                szname = "pkg.size"
+                                        elif szname == "csz":
+                                                szname = "pkg.csize"
+                                        else:
+                                                # Skip unknowns.
+                                                continue
+
+                                        self.attributes.setdefault(szname, 0)
+                                        self.attributes[szname] += int(szval)
+                                return
+                except (KeyError, TypeError, ValueError):
+                        # ignore broken set actions
                         pass
 
+                # Ensure facet and variant attributes are always lists.
+                if keyvalue[:10] == "pkg.facet.":
+                        # Possible facets list is spread over multiple actions.
+                        val = action.attrlist("value")
+                        if len(val) == 1 and val[0] == "":
+                                # No facets.
+                                val = []
+
+                        seen = self.attributes.setdefault("pkg.facet", [])
+                        for f in val:
+                                entry = "facet.%s" % f
+                                if entry not in seen:
+                                        # Prevent duplicates; it's possible a
+                                        # given facet may be valid for more than
+                                        # one unique variant combination that's
+                                        # allowed by current excludes.
+                                        seen.append(f)
+                        return
+                elif keyvalue == "pkg.variant":
+                        val = action.attrlist("value")
+                        if len(val) == 1 and val[0] == "":
+                                # No variants.
+                                val = []
+
+                        self.attributes[keyvalue] = [
+                            "variant.%s" % v
+                            for v in val
+                        ]
+                        return
+                elif keyvalue[:8] == "variant.":
+                        self.attributes[keyvalue] = action.attrlist("value")
+                        return
+
+                if keyvalue == "fmri":
+                        # Ancient manifest compatibility.
+                        keyvalue = "pkg.fmri"
+                self.attributes[keyvalue] = action.attrs["value"]
+
         @staticmethod
         def search_dict(file_path, excludes, return_line=False,
             log=None):
@@ -884,24 +1306,64 @@
                             "'false'" % ret))
 
         def get_size(self, excludes=EmptyI):
-                """Returns an integer representing the total size, in bytes, of
-                the Manifest's data payload.
+                """Returns an integer tuple of the form (size, csize), where
+                'size' represents the total uncompressed size, in bytes, of the
+                Manifest's data payload, and 'csize' represents the compressed
+                version of that.
 
-                'excludes' is a list of variants which should be allowed when
-                calculating the total.
-                """
+                'excludes' is a list of a list of variants and facets which
+                should be allowed when calculating the total."""
 
+                if self.excludes == excludes:
+                        excludes = EmptyI
+                assert excludes == EmptyI or self.excludes == EmptyI
+
+                csize = 0
                 size = 0
-                for a in self.gen_actions(excludes):
+
+                attrs = self.attributes
+                if ("pkg.size" in attrs and "pkg.csize" in attrs) and \
+                    (excludes == EmptyI or self.excludes == excludes):
+                        # If specified excludes match loaded excludes, then use
+                        # cached attributes; this is safe as manifest attributes
+                        # are reset or updated every time exclude_content,
+                        # set_content, or add_action is called.
+                        return (attrs["pkg.size"], attrs["pkg.csize"])
+
+                for a in self.gen_actions(excludes=excludes):
                         size += a.get_size()
-                return size
+                        csize += misc.get_pkg_otw_size(a)
+
+                if excludes == EmptyI:
+                        # Cache for future calls.
+                        attrs["pkg.size"] = size
+                        attrs["pkg.csize"] = csize
+
+                return (size, csize)
 
-        def __load_varcets(self):
-                """Private helper function to populate list of facets and
-                variants on-demand."""
+        def _get_varcets(self, excludes=EmptyI):
+                """Private helper function to get list of facets/variants."""
+
+                variants = defaultdict(set)
+                facets = defaultdict(set)
 
-                self._facets = {}
-                self._variants = {}
+                nexcludes = excludes
+                if nexcludes:
+                        # Facet filtering should never be applied when excluding
+                        # actions; only variant filtering.  This is ugly, but
+                        # our current variant/facet filtering system doesn't
+                        # allow you to be selective and various bits in
+                        # pkg.manifest assume you always filter on both so we
+                        # have to fake up a filter for facets.
+                        nexcludes = [
+                            x for x in excludes
+                            if x.__func__ != facet._allow_facet
+                        ]
+                        # Excludes list must always have zero or two items; so
+                        # fake second entry.
+                        nexcludes.append(lambda x: True)
+                        assert len(nexcludes) == 2
+
                 for action in self.gen_actions():
                         # append any variants and facets to manifest dict
                         attrs = action.attrs
@@ -911,29 +1373,27 @@
                                 continue
 
                         try:
-                                for v, d in chain(
-                                    izip(v_list, repeat(self._variants)),
-                                    izip(f_list, repeat(self._facets))):
-                                        try:
+                                for v, d in izip(v_list, repeat(variants)):
+                                        d[v].add(attrs[v])
+
+                                if not excludes or action.include_this(
+                                    nexcludes):
+                                        # While variants are package level (you
+                                        # can't install a package without
+                                        # setting the variant first), facets
+                                        # from the current action should only be
+                                        # included if the action is not
+                                        # excluded.
+                                        for v, d in izip(f_list, repeat(facets)):
                                                 d[v].add(attrs[v])
-                                        except KeyError:
-                                                d[v] = set([attrs[v]])
                         except TypeError:
                                 # Lists can't be set elements.
                                 raise actions.InvalidActionError(action,
                                     _("%(forv)s '%(v)s' specified multiple times") %
                                     {"forv": v.split(".", 1)[0], "v": v})
 
-        def __get_facets(self):
-                if self._facets is None:
-                        self.__load_varcets()
-                return self._facets
-
-        def __get_variants(self):
-                if self._variants is None:
-                        self.__load_varcets()
-                return self._variants
-
+                return (variants, facets)
+                
         def __getitem__(self, key):
                 """Return the value for the package attribute 'key'."""
                 return self.attributes[key]
@@ -953,9 +1413,6 @@
         def __contains__(self, key):
                 return key in self.attributes
 
-        facets = property(lambda self: self.__get_facets())
-        variants = property(lambda self: self.__get_variants())
-
 null = Manifest()
 
 class FactoredManifest(Manifest):
@@ -1003,7 +1460,7 @@
 
                 # Do we have a cached copy?
                 if not os.path.exists(self.pathname):
-                        if not contents:
+                        if contents is None:
                                 raise KeyError, fmri
                         # we have no cached copy; save one
                         # don't specify excludes so on-disk copy has
@@ -1044,8 +1501,6 @@
                 when downloading new manifests"""
                 self.actions = []
                 self.actions_bytype = {}
-                self._variants = None
-                self._facets = None
                 self.attributes = {}
                 self.loaded = False
 
@@ -1079,24 +1534,47 @@
                 # Ensure target cache directory and intermediates exist.
                 misc.makedirs(t_dir)
 
-                # create per-action type cache; use rename to avoid
-                # corrupt files if ^C'd in the middle
-                for n in self.actions_bytype.keys():
+                # create per-action type cache; use rename to avoid corrupt
+                # files if ^C'd in the middle.  All action types are considered
+                # so that empty cache files are created if no action of that
+                # type exists for the package (avoids full manifest loads
+                # later).
+                for n, acts in self.actions_bytype.iteritems():
                         t_prefix = "manifest.%s." % n
 
-                        fd, fn = tempfile.mkstemp(dir=t_dir, prefix=t_prefix)
-                        f = os.fdopen(fd, "wb")
+                        try:
+                                fd, fn = tempfile.mkstemp(dir=t_dir,
+                                    prefix=t_prefix)
+                        except EnvironmentError, e:
+                                raise apx._convert_error(e)
 
-                        for a in self.actions_bytype[n]:
-                                f.write("%s\n" % a)
-                        f.close()
-                        os.chmod(fn, PKG_FILE_MODE)
-                        portable.rename(fn, self.__cache_path("manifest.%s" % n))
+                        f = os.fdopen(fd, "wb")
+                        try:
+                                for a in acts:
+                                        f.write("%s\n" % a)
+                                if n == "set":
+                                        # Add supplemental action data; yes this
+                                        # does mean the cache is not the same as
+                                        # retrieved manifest, but that's ok.
+                                        # Signature verification is done using
+                                        # the raw manifest.
+                                        f.writelines(self._gen_attrs_to_str())
+                        except EnvironmentError, e:
+                                raise apx._convert_error(e)
+                        finally:
+                                f.close()
+
+                        try:
+                                os.chmod(fn, PKG_FILE_MODE)
+                                portable.rename(fn,
+                                    self.__cache_path("manifest.%s" % n))
+                        except EnvironmentError, e:
+                                raise apx._convert_error(e)
 
                 def create_cache(name, refs):
                         try:
                                 fd, fn = tempfile.mkstemp(dir=t_dir,
-                                    prefix="manifest.dircache.")
+                                    prefix=name + ".")
                                 with os.fdopen(fd, "wb") as f:
                                         f.writelines(refs())
                                 os.chmod(fn, PKG_FILE_MODE)
@@ -1203,30 +1681,66 @@
                         for a in Manifest.gen_actions_by_type(self, atype,
                             excludes):
                                 yield a
-                else:
-                        if excludes == EmptyI:
-                                excludes = self.excludes
-                        assert excludes == self.excludes or \
-                            self.excludes == EmptyI
-                        # we have a cached copy - use it
-                        mpath = self.__cache_path("manifest.%s" % atype)
+                        return
+
+                if excludes == EmptyI:
+                        excludes = self.excludes
+                assert excludes == self.excludes or self.excludes == EmptyI
 
-                        if not os.path.exists(mpath):
-                                return # no such action in this manifest
+                if atype in self._absent_cache:
+                        # No such action in the manifest; must be done *after*
+                        # asserting excludes are correct to avoid hiding
+                        # failures.
+                        return
 
+                # Assume a cached copy exists; if not, tag the action type to
+                # avoid pointless I/O later.
+                mpath = self.__cache_path("manifest.%s" % atype)
+
+                try:
                         with open(mpath, "rb") as f:
                                 for l in f:
                                         a = actions.fromstr(l.rstrip())
                                         if not excludes or \
                                             a.include_this(excludes):
                                                 yield a
+                except EnvironmentError, e:
+                        if e.errno == errno.ENOENT:
+                                self._absent_cache.append(atype)
+                                return # no such action in this manifest
+                        raise apx._convert_error(e)
 
-        def gen_mediators(self, excludes):
+        def gen_facets(self, excludes=EmptyI, patterns=EmptyI):
+                """A generator function that returns the supported facet
+                attributes (strings) for this package based on the specified (or
+                current) excludes that also match at least one of the patterns
+                provided.  Facets must be true or false so a list of possible
+                facet values is not returned."""
+
+                if not self.loaded and not self.__load_attributes():
+                        self.__load()
+                return Manifest.gen_facets(self, excludes=excludes,
+                    patterns=patterns)
+
+        def gen_variants(self, excludes=EmptyI, patterns=EmptyI):
+                """A generator function that yields a list of tuples of the form
+                (variant, [values]).  Where 'variant' is the variant attribute
+                name (e.g. 'variant.arch') and '[values]' is a list of the
+                variant values supported by this package.  Variants returned are
+                those allowed by the specified (or current) excludes that also
+                match at least one of the patterns provided."""
+
+                if not self.loaded and not self.__load_attributes():
+                        self.__load()
+                return Manifest.gen_variants(self, excludes=excludes,
+                    patterns=patterns)
+
+        def gen_mediators(self, excludes=EmptyI):
                 """A generator function that yields set actions expressing the
                 set of possible mediations for this package.
                 """
                 self.__load_cached_data("manifest.mediatorcache")
-                return Manifest.gen_mediators(self, excludes)
+                return Manifest.gen_mediators(self, excludes=excludes)
 
         def __load_attributes(self):
                 """Load attributes dictionary from cached set actions;
@@ -1241,8 +1755,21 @@
                                 if not self.excludes or \
                                     a.include_this(self.excludes):
                                         self.fill_attributes(a)
+
                 return True
 
+        def get_size(self, excludes=EmptyI):
+                """Returns an integer tuple of the form (size, csize), where
+                'size' represents the total uncompressed size, in bytes, of the
+                Manifest's data payload, and 'csize' represents the compressed
+                version of that.
+
+                'excludes' is a list of a list of variants and facets which
+                should be allowed when calculating the total."""
+                if not self.loaded and not self.__load_attributes():
+                        self.__load()
+                return Manifest.get_size(self, excludes=excludes)
+
         def __getitem__(self, key):
                 if not self.loaded and not self.__load_attributes():
                         self.__load()
@@ -1301,6 +1828,12 @@
                     origin_exclude=origin_exclude,
                     self_exclude=self_exclude)
 
+        def store(self, mfst_path):
+                """Store the manifest contents to disk."""
+                if not self.loaded:
+                        self.__load()
+                super(FactoredManifest, self).store(mfst_path)
+
         @property
         def pathname(self):
                 """The absolute pathname of the file containing the manifest."""
--- a/src/modules/misc.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/misc.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 
 """
 Misc utility functions used by the packaging system.
@@ -32,6 +32,7 @@
 import collections
 import datetime
 import errno
+import fnmatch
 import getopt
 import hashlib
 import itertools
@@ -41,6 +42,7 @@
 import re
 import resource
 import shutil
+import signal
 import simplejson as json
 import socket
 import struct
@@ -52,6 +54,8 @@
 import urlparse
 import zlib
 
+from collections import defaultdict
+
 from stat import S_IFMT, S_IMODE, S_IRGRP, S_IROTH, S_IRUSR, S_IRWXU, \
     S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISLNK, S_ISREG, S_ISSOCK, \
     S_IWUSR, S_IXGRP, S_IXOTH
@@ -65,6 +69,9 @@
 from pkg.client.imagetypes import img_type_names, IMG_NONE
 from pkg.pkggzip import PkgGzipFile
 
+# Default path where the temporary directories will be created.
+DEFAULT_TEMP_PATH = "/var/tmp"
+
 # Minimum number of days to issue warning before a certificate expires
 MIN_WARN_DAYS = datetime.timedelta(days=30)
 
@@ -446,7 +453,7 @@
 def bytes_to_str(nbytes, fmt="%(num).2f %(unit)s"):
         """Returns a human-formatted string representing the number of bytes
         in the largest unit possible.
-        
+
         If provided, 'fmt' should be a string which can be formatted
         with a dictionary containing a float 'num' and strings 'unit' and
         'shortunit'.  The default format prints, for example, '3.23 MB' """
@@ -491,8 +498,8 @@
         pkg.csize.  If that value isn't available, it returns pkg.size.
         If pkg.size isn't available, return zero."""
 
-        size = action.attrs.get("pkg.csize", 0)
-        if size == 0:
+        size = action.attrs.get("pkg.csize")
+        if size is None:
                 size = action.attrs.get("pkg.size", 0)
 
         return int(size)
@@ -1048,8 +1055,6 @@
         settings when creating temporary files/directories.  Otherwise,
         return a path that the caller should pass to tempfile instead."""
 
-        default_root = "/var/tmp"
-
         # In Python's tempfile module, the default temp directory
         # includes some paths that are suboptimal for holding large numbers
         # of files.  If the user hasn't set TMPDIR, TEMP, or TMP in the
@@ -1060,7 +1065,21 @@
                 if env_val:
                         return None
 
-        return default_root
+        return DEFAULT_TEMP_PATH
+
+def get_temp_root_path():
+        """Return the directory path where the temporary directories or
+        files should be created. If the environment has set TMPDIR
+        or TEMP or TMP then return the corresponding value else return the
+        default value."""
+
+        temp_env = [ "TMPDIR", "TEMP", "TMP" ]
+        for env in temp_env:
+                env_val = os.getenv(env)
+                if env_val:
+                        return env_val
+
+        return DEFAULT_TEMP_PATH
 
 def parse_uri(uri, cwd=None):
         """Parse the repository location provided and attempt to transform it
@@ -1188,30 +1207,27 @@
                 for name in filenames:
                         path = os.path.join(dirpath, name)
                         portable.chown(path, uid, gid)
-def opts_parse(op, api_inst, args, table, pargs_limit, usage_cb):
+
+
+def opts_parse(op, args, opts_table, opts_mapping, usage_cb=None):
         """Generic table-based options parsing function.  Returns a tuple
-        consisting of a dictionary of parsed options and the remaining
-        unparsed options.
+        consisting of a list of parsed options in the form (option, argument)
+        and the remaining unparsed options. The parsed-option list may contain
+        duplicates if an option is passed multiple times.
 
         'op' is the operation being performed.
 
-        'api_inst' is an image api object that is passed to options handling
-        callbacks (passed in via 'table').
-
         'args' is the arguments that should be parsed.
 
-        'table' is a list of options and callbacks.Each entry is either a
-        a tuple or a callback function.
-
-        tuples in 'table' specify allowable options and have the following
-        format:
-
-                (<short opt>, <long opt>, <key>, <default value>)
-
-        An example of a short opt is "f", which maps to a "-f" option.  An
-        example of a long opt is "foo", which maps to a "--foo" option.  Key
-        is the value of this option in the parsed option dictionary.  The
-        default value not only represents the default value assigned to the
+        'opts_table' is a list of options the operation supports.
+        The format of the list entries should be a tuple containing the
+        option and its default value:
+            (option, default_value)
+        It is valid to have other entries in the list when they are required
+        for additional option processing elsewhere. These are ignore here. If
+        the list entry is a tuple it must conform to the format oulined above.
+
+        The default value not only represents the default value assigned to the
         option, but it also implicitly determines how the option is parsed.  If
         the default value is True or False, the option doesn't take any
         arguments, can only be specified once, and if specified it inverts the
@@ -1224,139 +1240,98 @@
         specified multiple times, and if specified its value will be a list
         with all the specified argument values.
 
-        callbacks in 'table' specify callback functions that are invoked after
-        all options have been parsed.  Callback functions must have the
-        following signature:
-                callback(api_inst, opts, opts_new)
-
-        The opts parameter is a dictionary containing all the raw, parsed
-        options.  Callbacks should never update the contents of this
-        dictionary.  The opts_new parameter is a dictionary which is initially
-        a copy of the opts dictionary.  This is the dictionary that will be
-        returned to the caller of opts_parse().  If a callback function wants
-        to update the arguments dictionary that will be returned to the
-        caller, they should make all their updates to the opts_new dictionary.
-
-        'pargs_limit' specified how to handle extra arguments not parsed by
-        getops.  A value of -1 indicates that we allow an unlimited number of
-        extra arguments.  A value of 0 or greater indicates the number of
-        allowed additional unparsed options.
+        'opts_mapping' is a dict containing a mapping between the option name
+        and the short and long CLI specifier for that option in the form
+        { option : (short, long), ... }
+
+        An example of a short opt is "f", which maps to a "-f" option.  An
+        example of a long opt is "foo", which maps to a "--foo" option.  Option
+        is the value of this option in the parsed option dictionary.
 
         'usage_cb' is a function pointer that should display usage information
         and will be invoked if invalid arguments are detected."""
 
-
-        assert type(table) == list
-
-        # return dictionary
-        rv = dict()
-
-        # option string passed to getopt
+        # list for getopt long options
+        opts_l_list = []
+        # getopt str for short options
         opts_s_str = ""
-        # long options list passed to getopt
-        opts_l_list = list()
 
         # dict to map options returned by getopt to keys
         opts_keys = dict()
 
-        # sanity checking to make sure each option is unique
-        opts_s_set = set()
-        opts_l_set = set()
-        opts_seen = dict()
-
-        # callbacks to invoke after processing options
-        callbacks = []
-
-        # process each option entry
-        for entry in table:
-                # check for a callback
+        for entry in opts_table:
+                # option table contains functions for verification, ignore here
                 if type(entry) != tuple:
-                        callbacks.append(entry)
                         continue
-
-                # decode the table entry
-                # s: a short option, ex: -f
-                # l: a long option, ex: --foo
-                # k: the key value for the options dictionary
-                # v: the default value
-                (s, l, k, v) = entry
-
+                opt, default, = entry
+                assert opt in opts_mapping
+                sopt, lopt = opts_mapping[opt]
                 # make sure an option was specified
-                assert s or l
-                # sanity check the default value
-                assert (v == None) or (v == []) or \
-                    (type(v) == bool) or (type(v) == int)
-                # make sure each key is unique
-                assert k not in rv
-                # initialize the default return dictionary entry.
-                rv[k] = v
-                if l:
-                        # make sure each option is unique
-                        assert set([l]) not in opts_l_set
-                        opts_l_set |= set([l])
-
-                        if type(v) == bool:
-                                v = not v
-                                opts_l_list.append("%s" % l)
-                        elif type(v) == int:
-                                opts_l_list.append("%s" % l)
+                assert sopt or lopt
+                if lopt != "":
+                        if default is None or type(default) == list:
+                                opts_l_list.append("%s=" % lopt)
                         else:
-                                opts_l_list.append("%s=" % l)
-                        opts_keys["--%s" % l] = k
-                if s:
-                        # make sure each option is unique
-                        assert set([s]) not in opts_s_set
-                        opts_s_set |= set([s])
-
-                        if type(v) == bool:
-                                v = not v
-                                opts_s_str += "%s" % s
-                        elif type(v) == int:
-                                opts_s_str += "%s" % s
+                                opts_l_list.append("%s" % lopt)
+                        opts_keys["--%s" % lopt] = opt
+                if sopt != "":
+                        if default is None or type(default) == list:
+                                opts_s_str += "%s:" % sopt
                         else:
-                                opts_s_str += "%s:" % s
-                        opts_keys["-%s" % s] = k
-
-        # parse options
+                                opts_s_str += "%s" % sopt
+                        opts_keys["-%s" % sopt] = opt
+
+        # Parse options.
         try:
                 opts, pargs = getopt.getopt(args, opts_s_str, opts_l_list)
         except getopt.GetoptError, e:
                 usage_cb(_("illegal option -- %s") % e.opt, cmd=op)
 
-        if (pargs_limit >= 0) and (pargs_limit < len(pargs)):
-                usage_cb(_("illegal argument -- %s") % pargs[pargs_limit],
-                    cmd=op)
-
-        # update options dictionary with the specified options
-        for opt, arg in opts:
-                k = opts_keys[opt]
-                v = rv[k]
-
-                # check for duplicate options
-                if k in opts_seen and (type(v) != list and type(v) != int):
-                        if opt == opts_seen[k]:
-                                usage_cb(_("option '%s' repeated") % opt,
-                                    cmd=op)
-                        usage_cb(_("'%s' and '%s' have the same meaning") %
-                            (opts_seen[k], opt), cmd=op)
-                opts_seen[k] = opt
-
-                # update the return dict value
-                if type(v) == bool:
-                        rv[k] = not rv[k]
-                elif type(v) == list:
-                        rv[k].append(arg)
-                elif type(v) == int:
-                        rv[k] += 1
+        def get_default(option):
+                """Find the default value for a given option from opts_table."""
+                for x in opts_table:
+                        if type(x) != tuple:
+                                continue
+                        opt, default = x
+                        if option == opt:
+                                return default
+
+        # Assemble the options dictionary by passing in the right data types and
+        # take care of duplicates.
+        opt_dict = {}
+        for x in opts:
+                cli_opt, arg = x
+                opt = opts_keys[cli_opt]
+
+                # Determine required option type based on the default value.
+                default = get_default(opt)
+
+                # Handle duplicates for integer and list types.
+                if type(default) == int:
+                        if opt in opt_dict:
+                                opt_dict[opt] += 1
+                        else:
+                                opt_dict[opt] = 1
+                        continue
+                if type(default) == list:
+                        if opt in opt_dict:
+                                opt_dict[opt].append(arg)
+                        else:
+                                opt_dict[opt] = [arg]
+                        continue
+
+                # Boolean and string types can't be repeated.
+                if opt in opt_dict:
+                        raise api_errors.InvalidOptionError(
+                            api_errors.InvalidOptionError.OPT_REPEAT, [opt])
+
+                # For boolean options we have to toggle the default value.
+                if type(default) == bool:
+                        opt_dict[opt] = not default
                 else:
-                        rv[k] = arg
-
-        # invoke callbacks (cast to set() to eliminate dups)
-        rv_updated = rv.copy()
-        for cb in set(callbacks):
-                cb(op, api_inst, rv, rv_updated)
-
-        return (rv_updated, pargs)
+                        opt_dict[opt] = arg
+
+        return opt_dict, pargs
 
 def api_cmdpath():
         """Returns the path to the executable that is invoking the api client
@@ -2453,3 +2428,52 @@
                 # this will encode 8 bit strings into unicode
                 s = s.decode("utf-8", "replace")
         return s
+
+def yield_matching(pat_prefix, items, patterns):
+        """Helper function for yielding items that match one of the provided
+        patterns."""
+
+        if patterns:
+                # Normalize patterns and determine whether to glob.
+                npatterns = []
+                for p in patterns:
+                        if pat_prefix:
+                                pat = p.startswith(pat_prefix) and \
+                                    p or (pat_prefix + p)
+                        else:
+                                pat = p
+                        if "*" in p or "?" in p:
+                                pat = re.compile(fnmatch.translate(pat)).match
+                                glob_match = True
+                        else:
+                                glob_match = False
+
+                        npatterns.append((pat, glob_match))
+                patterns = npatterns
+                npatterns = None
+
+        for item in items:
+                for (pat, glob_match) in patterns:
+                        if glob_match:
+                                if pat(item):
+                                        break
+                        elif item == pat:
+                                break
+                else:
+                        if patterns:
+                                continue
+                # No patterns or matched at least one.
+                yield item
+
+
+sigdict = defaultdict(list)
+
+def signame(signal_number):
+        """convert signal number to name(s)"""
+        if not sigdict:
+                for name in dir(signal):
+                        if name.startswith("SIG") and "_" not in name:
+                                sigdict[getattr(signal, name)].append(name)
+
+        return "/".join(sigdict.get(signal_number, ["Unnamed signal: %d" %
+            signal_number]))
--- a/src/modules/p5i.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/p5i.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -57,10 +57,10 @@
 
         'data' or 'fileobj' or 'location' must be provided."""
 
-        if not data and not location and not fileobj:
+        if data is None and location is None and fileobj is None:
                 raise api_errors.InvalidResourceLocation(location)
 
-        if location:
+        if location is not None:
                 if location.find("://") == -1 and \
                     not location.startswith("file:/"):
                         # Convert the file path to a URI.
@@ -76,7 +76,7 @@
                             location=location)
 
         try:
-                if data:
+                if data is not None:
                         dump_struct = json.loads(data)
                 else:
                         dump_struct = json.load(fileobj)
--- a/src/modules/p5p.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/p5p.py	Wed Aug 14 11:12:35 2013 +0530
@@ -808,7 +808,7 @@
 
                 # No catalog data found for publisher; construct a catalog
                 # in memory based on packages found for publisher.
-                cat = pkg.catalog.Catalog(batch_mode=True, sign=False)
+                cat = pkg.catalog.Catalog(batch_mode=True)
                 manpath = os.path.join(pubpath, "pkg") + os.path.sep
                 for name in self.__extract_offsets:
                         if name.startswith(manpath) and name.count("/") == 4:
--- a/src/modules/query_parser.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/query_parser.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -1411,6 +1411,12 @@
                 elif self._data_token_offset.has_entity(term):
                         offsets = set([
                             self._data_token_offset.get_id(term)])
+                else:
+                        # Close the dictionaries since there are
+                        # no more results to yield.
+                        self._close_dicts()
+                        return
+
                 # Restrict results by package name.
                 if not self.pkg_name_wildcard:
                         try:
--- a/src/modules/server/api.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/server/api.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import cherrypy
@@ -190,6 +190,10 @@
                         ifmri = pkg.fmri.PkgFmri(a.attrs["fmri"],
                             build_release="5.11")
                         iver = ifmri.version
+                        # Versionless incorporations don't make sense so don't
+                        # recurse any further.
+                        if not iver:
+                                continue
                         recurse = False
                         for ver, flist in cat.fmris_by_version(ifmri.pkg_name,
                             pubs=pubs):
@@ -323,8 +327,8 @@
                         states = None
 
                         links = hardlinks = files = dirs = dependencies = None
-                        summary = size = licenses = cat_info = description = \
-                            None
+                        summary = csize = size = licenses = cat_info = \
+                            description = None
 
                         if cat_opts & info_needed:
                                 summary, description, cat_info, dependencies = \
@@ -355,7 +359,8 @@
                                         licenses = self.__licenses(mfst)
 
                                 if PackageInfo.SIZE in info_needed:
-                                        size = mfst.get_size(excludes=excludes)
+                                        size, csize = mfst.get_size(
+                                            excludes=excludes)
 
                                 if act_opts & info_needed:
                                         if PackageInfo.LINKS in info_needed:
@@ -380,9 +385,10 @@
                             publisher=pub, version=release,
                             build_release=build_release, branch=branch,
                             packaging_date=packaging_date, size=size,
-                            pfmri=f, licenses=licenses, links=links,
-                            hardlinks=hardlinks, files=files, dirs=dirs,
-                            dependencies=dependencies, description=description))
+                            csize=csize, pfmri=f, licenses=licenses,
+                            links=links, hardlinks=hardlinks, files=files,
+                            dirs=dirs, dependencies=dependencies,
+                            description=description))
                 return {
                     self.INFO_FOUND: pis,
                     self.INFO_MISSING: notfound,
--- a/src/modules/server/depot.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/server/depot.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,10 +21,11 @@
 #
 
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import cherrypy
+from cherrypy._cptools import HandlerTool
 from cherrypy.lib.static import serve_file
 from email.utils import formatdate
 from cherrypy.process.plugins import SimplePlugin
@@ -44,6 +45,7 @@
 import httplib
 import inspect
 import itertools
+import math
 import os
 import random
 import re
@@ -68,7 +70,6 @@
 
 import pkg
 import pkg.actions as actions
-import pkg.catalog as catalog
 import pkg.config as cfg
 import pkg.fmri as fmri
 import pkg.indexer as indexer
@@ -88,56 +89,10 @@
         """Dummy object used for dispatch method mapping."""
         pass
 
+
 class _Depot(object):
         """Private, abstract, base class for all Depot classes."""
-
-        nasty = 0
-
-        def set_nasty(self, level):
-                """Set the nasty level using an integer."""
-
-                self.nasty = level
-
-        def is_nasty(self):
-                """Returns true if nasty has been enabled."""
-
-                if self.nasty > 0:
-                        return True
-                return False
-
-        def need_nasty(self):
-                """Randomly returns true when the server should misbehave."""
-
-                if random.randint(1, 100) <= self.nasty:
-                        return True
-                return False
-
-        def need_nasty_bonus(self, bonus=0):
-                """Used to temporarily apply extra nastiness to an operation."""
-
-                if self.nasty + bonus > 95:
-                        nasty = 95
-                else:
-                        nasty = self.nasty + bonus
-
-                if random.randint(1, 100) <= nasty:
-                        return True
-                return False
-
-        def need_nasty_occasionally(self):
-                if random.randint(1, 500) <= self.nasty:
-                        return True
-                return False
-
-        def need_nasty_infrequently(self):
-                if random.randint(1, 2000) <= self.nasty:
-                        return True
-                return False
-
-        def need_nasty_rarely(self):
-                if random.randint(1, 20000) <= self.nasty:
-                        return True
-                return False
+        pass
 
 
 class DepotHTTP(_Depot):
@@ -189,19 +144,25 @@
         content_root = None
         web_root = None
 
-        def __init__(self, repo, dconf):
+        def __init__(self, repo, dconf, request_pub_func=None):
                 """Initialize and map the valid operations for the depot.  While
                 doing so, ensure that the operations have been explicitly
-                "exposed" for external usage."""
+                "exposed" for external usage.
+
+                request_pub_func, if set is a function that gets called with
+                cherrypy.request.path_info that returns the publisher used
+                for a given request.
+                """
 
                 # This lock is used to protect the depot from multiple
                 # threads modifying data structures at the same time.
-                self.__lock = pkg.nrlock.NRLock()
+                self._lock = pkg.nrlock.NRLock()
 
                 self.cfg = dconf
                 self.repo = repo
                 self.flist_requests = 0
                 self.flist_file_requests = 0
+                self.request_pub_func = request_pub_func
 
                 content_root = dconf.get_property("pkg", "content_root")
                 pkg_root = dconf.get_property("pkg", "pkg_root")
@@ -348,6 +309,8 @@
                 that isn't viewed as an unreasonable limitation.
                 """
 
+                if self.request_pub_func:
+                        return self.request_pub_func(cherrypy.request.path_info)
                 try:
                         req_pub = cherrypy.request.path_info.strip("/").split(
                             "/")[0]
@@ -433,7 +396,7 @@
         def __map_pub_ops(self, pub_prefix):
                 # Map the publisher into the depot's operation namespace if
                 # needed.
-                self.__lock.acquire() # Prevent race conditions.
+                self._lock.acquire() # Prevent race conditions.
                 try:
                         pubattr = getattr(self, pub_prefix, None)
                         if not pubattr:
@@ -446,7 +409,7 @@
                                         opattr = getattr(self, op)
                                         setattr(pubattr, op, opattr)
                 finally:
-                        self.__lock.release()
+                        self._lock.release()
 
         @cherrypy.expose
         def default(self, *tokens, **params):
@@ -1361,22 +1324,24 @@
                 lsummary.seek(0)
 
                 self.__set_response_expires("info", 86400*365, 86400*365)
+                size, csize = m.get_size()
                 return """\
-          Name: %s
-       Summary: %s
-     Publisher: %s
-       Version: %s
- Build Release: %s
-        Branch: %s
-Packaging Date: %s
-          Size: %s
-          FMRI: %s
+           Name: %s
+        Summary: %s
+      Publisher: %s
+        Version: %s
+  Build Release: %s
+         Branch: %s
+ Packaging Date: %s
+           Size: %s
+Compressed Size: %s
+           FMRI: %s
 
 License:
 %s
 """ % (name, summary, pub, ver.release, ver.build_release,
-    ver.branch, ver.get_timestamp().strftime("%c"),
-    misc.bytes_to_str(m.get_size()), pfmri, lsummary.read())
+    ver.branch, ver.get_timestamp().strftime("%c"), misc.bytes_to_str(size),
+    misc.bytes_to_str(csize), pfmri, lsummary.read())
 
         @cherrypy.tools.response_headers(headers=[(
             "Content-Type", p5i.MIME_TYPE)])
@@ -1442,7 +1407,7 @@
                 self.__set_response_expires("publisher", 86400*365, 86400*365)
                 return buf.getvalue()
 
-        def __get_matching_p5i_data(self, rstore, matcher, pfmri):
+        def __get_matching_p5i_data(self, rstore, pfmri):
                 # Attempt to find matching entries in the catalog.
                 try:
                         pub = self.repo.get_publisher(rstore.publisher)
@@ -1456,10 +1421,10 @@
                         return ""
 
                 try:
-                        matches, unmatched = catalog.extract_matching_fmris(
-                            cat.fmris(), patterns=[pfmri],
-                            constraint=pkg.version.CONSTRAINT_AUTO,
-                            matcher=matcher)
+                        matches = [fmri for fmri, states, attrs in \
+                            cat.gen_packages(patterns=[pfmri],
+                            return_fmris=True)]
+                             
                 except Exception, e:
                         # If this fails, it's ok to raise an exception since bad
                         # input was likely provided.
@@ -1468,7 +1433,8 @@
 
                 if not matches:
                         return ""
-                elif matcher in (fmri.exact_name_match, fmri.glob_match):
+
+                if not "@" in pfmri or "*" in pfmri:
                         # When using wildcards or exact name match, trim the
                         # results to only the unique package stems.
                         matches = sorted(set([m.pkg_name for m in matches]))
@@ -1526,18 +1492,6 @@
                         end = len(pfmri) - len(".p5i")
                         pfmri = pfmri[:end]
 
-                matcher = None
-                if "*" not in pfmri and "@" not in pfmri:
-                        matcher = fmri.exact_name_match
-                elif "*" in pfmri:
-                        matcher = fmri.glob_match
-                        try:
-                                # XXX 5.11 needs to be saner
-                                pfmri = fmri.MatchingPkgFmri(pfmri, "5.11")
-                        except Exception, e:
-                                raise cherrypy.HTTPError(httplib.BAD_REQUEST,
-                                    str(e))
-
                 output = ""
                 prefix = self._get_req_pub()
                 for rstore in self.repo.rstores:
@@ -1545,8 +1499,7 @@
                                 continue
                         if prefix and prefix != rstore.publisher:
                                 continue
-                        output += self.__get_matching_p5i_data(rstore,
-                            matcher, pfmri)
+                        output += self.__get_matching_p5i_data(rstore, pfmri)
 
                 if output == "":
                         raise cherrypy.HTTPError(httplib.NOT_FOUND, _("No "
@@ -1573,11 +1526,51 @@
                             "to generate statistics."))
                 return out + "\n"
 
+def nasty_before_handler(nasty_depot, maxroll=100):
+        """Cherrypy Tool callable which generates various problems prior to a
+        request.  Possible outcomes: retryable HTTP error, short nap."""
+
+        # Must be set in _cp_config on associated request handler.
+        assert nasty_depot
+
+        # Adjust nastiness values once per incoming request.
+        nasty_depot.nasty_housekeeping()
+
+        # Just roll the main nasty dice once.
+        if not nasty_depot.need_nasty(maxroll=maxroll):
+                return False
+
+        while True:
+                roll = random.randint(0, 10)
+                if roll == 0:
+                        nasty_depot.nasty_nap()
+                        if random.randint(0, 1) == 1:
+                                # Nap was enough. Let the normal handler run.
+                                return False
+                if 1 <= roll <= 8:
+                        nasty_depot.nasty_raise_error()
+                else:
+                        cherrypy.log("NASTY: return bogus or empty response")
+                        response = cherrypy.response
+                        response.body = random.choice(['',
+                            'set this is a bogus action',
+                            'Instead of office chair, '
+                                'package contained bobcat.',
+                            '{"this is a": "fragment of json"}'])
+                        return True
+        return False
+
 
 class NastyDepotHTTP(DepotHTTP):
         """A class that creates a depot that misbehaves.  Naughty
         depots are useful for testing."""
 
+        # Nastiness ebbs and flows in a sinusoidal NASTY_CYCLE length pattern.
+        # The magnitude of the effect is governed by NASTY_MULTIPLIER.
+        # See also nasty_housekeeping().
+        NASTY_CYCLE = 200
+        NASTY_MULTIPLIER = 1.0
+
         def __init__(self, repo, dconf):
                 """Initialize."""
 
@@ -1593,23 +1586,200 @@
                 self.requested_catalogs = []
                 self.requested_manifests = []
 
-                cherrypy.tools.nasty_httperror = cherrypy.Tool('before_handler',
-                    NastyDepotHTTP.nasty_retryable_error)
+                self.nasty_level = \
+                    int(dconf.get_property("nasty", "nasty_level"))
+                self.nasty_sleep = \
+                    int(dconf.get_property("nasty", "nasty_sleep"))
+
+                self.nasty_cycle = self.NASTY_CYCLE
+                self.maxroll_adj = 1.0
+
+                cherrypy.log("NASTY Depot Started")
+                cherrypy.log("NASTY nasty=%d, nasty_sleep=%d" % \
+                    (self.nasty_level, self.nasty_sleep))
+
+                # See CherryPy HandlerTool docs; this sets up a special
+                # tool which can prevent the main request body from running
+                # when needed.
+                cherrypy.tools.nasty_before = HandlerTool(nasty_before_handler)
+
+                self._cp_config = {
+                    # Turn on this tool for all requests.
+                    'tools.nasty_before.on': True,
+                    #
+                    # This is tricky: we poke a reference to ourself into our
+                    # own _cp_config, specifically so that we can get this
+                    # reference passed by cherrypy as an input argument to our
+                    # nasty_before tool, so that it can in turn call methods
+                    # back on this object.
+                    #
+                    'tools.nasty_before.nasty_depot': self
+                }
+
+                # Set up a list of errors that we can pick from when we
+                # want to return an error at random to the client.  Errors
+                # are weighted by how often we want them to happen; the loop
+                # below then puts them into a pick-list.
+                errors = {
+                    httplib.REQUEST_TIMEOUT: 10,
+                    httplib.BAD_GATEWAY: 10,
+                    httplib.GATEWAY_TIMEOUT: 10,
+                    httplib.FORBIDDEN: 2,
+                    httplib.NOT_FOUND: 2,
+                    httplib.BAD_REQUEST: 2
+                }
+
+                self.errlist = []
+                for x, n in errors.iteritems():
+                        for i in range(0, n):
+                                self.errlist.append(x)
+                cherrypy.log("NASTY Depot Error List: %s" % str(self.errlist))
+
+        def nasty_housekeeping(self):
+                # Generate a sine wave (well, half of one) which is NASTY_CYCLE
+                # steps long and use that to increase maxroll (thus reducing
+                # the nastiness).  The causes nastiness to come and go in
+                # waves, which helps to prevent excessive nastiness from
+                # impeding all progress.
+                #
+                # The intention is for this to get adjusted once per request.
+
+                # Prevent races updating global nastiness information.
+                # Note that this isn't strictly necessary since nasty_cycle
+                # and maxroll_adj are just numbers and races are essentially
+                # harmless, but this is here so that we don't screw things up
+                # in the future.
+                self._lock.acquire()
 
-        # Method for CherryPy tool for Nasty Depot
-        def nasty_retryable_error(self, bonus=0):
-                """A static method that's used by the cherrypy tools,
-                and in depot code, to generate a retryable HTTP error."""
+                self.nasty_cycle = (self.nasty_cycle + 1) % self.NASTY_CYCLE
+                self.maxroll_adj = 1 + self.NASTY_MULTIPLIER * \
+                    math.sin(self.nasty_cycle *
+                        (math.pi / self.NASTY_CYCLE))
+                if self.nasty_cycle == 0:
+                        cherrypy.log("NASTY nastiness at min")
+                if self.nasty_cycle == self.NASTY_CYCLE / 2:
+                        cherrypy.log("NASTY nastiness at max")
+
+                self._lock.release()
+
+        def need_nasty(self, maxroll=100):
+                """Randomly returns true when the server should misbehave."""
+
+                # Apply the sine wave adjustment to maxroll-- preserving the
+                # possiblity that bad things can still sporadically happen.
+                # n.b. we don't bother to pick up the lock here.
+                maxroll = int(maxroll * self.maxroll_adj)
+
+                roll = random.randint(1, maxroll)
+                if roll <= self.nasty_level:
+                        return True
+                return False
+
+        def need_nasty_2(self):
+                """Nastiness sometimes."""
+                return self.need_nasty(maxroll=500)
+
+        def need_nasty_3(self):
+                """Nastiness less often."""
+                return self.need_nasty(maxroll=2000)
 
-                retryable_errors = [httplib.REQUEST_TIMEOUT,
-                    httplib.BAD_GATEWAY, httplib.GATEWAY_TIMEOUT]
+        def need_nasty_4(self):
+                """Nastiness very rarely."""
+                return self.need_nasty(maxroll=20000)
+
+        def nasty_raise_error(self):
+                """Raise an http error from self.errlist."""
+                code = random.choice(self.errlist)
+                cherrypy.log("NASTY: Random HTTP error: %d" % code)
+                raise cherrypy.HTTPError(code)
+
+        def nasty_nap(self):
+                """Sleep for a few seconds."""
+                cherrypy.log("NASTY: sleep for %d secs" % self.nasty_sleep)
+                time.sleep(self.nasty_sleep)
+
+        @cherrypy.expose
+        def nasty(self, *tokens):
+                try:
+                        nasty_level = int(tokens[0])
+                except (IndexError, ValueError):
+                        raise cherrypy.HTTPError(httplib.BAD_REQUEST)
+                if nasty_level < 0 or nasty_level > 100:
+                        raise cherrypy.HTTPError(httplib.BAD_REQUEST)
+                cherrypy.log("Nastiness set to %d by client request" %
+                    nasty_level)
+                self.nasty_level = nasty_level
+
+        # Disable the before handler for this request.
+        nasty._cp_config = { "tools.nasty_before.on": False }
+
+        @cherrypy.tools.response_headers(headers=\
+            [("Content-Type", "text/plain; charset=utf-8")])
+        def versions_0(self, *tokens):
+                """Output a text/plain list of valid operations, and their
+                versions, supported by the repository."""
 
                 # NASTY
-                # emit error code that client should know how to retry
-                if self.need_nasty_bonus(bonus):
-                        code = retryable_errors[random.randint(0,
-                            len(retryable_errors) - 1)]
-                        raise cherrypy.HTTPError(code)
+                # emit an X-Ipkg-Error HTTP unauthorized response.
+                if self.need_nasty_3():
+                        cherrypy.log("NASTY versions_0: X-Ipkg-Error")
+                        response = cherrypy.response
+                        response.status = httplib.UNAUTHORIZED
+                        response.headers["X-Ipkg-Error"] = random.choice(["ENT",
+                            "LIC", "SVR", "MNT", "YYZ", ""])
+                        return ""
+
+                # NASTY
+                # Serve up versions header but no versions
+                if self.need_nasty_3():
+                        cherrypy.log("NASTY versions_0: header but no versions")
+                        versions = "pkg-server %s\n" % pkg.VERSION
+                        return versions
+
+                # NASTY
+                # Serve up bogus versions by adding/subtracting from
+                # the actual version numbers-- we use a normal distribution
+                # to keep the perturbations small.
+                if self.need_nasty_2():
+                        cherrypy.log("NASTY versions_0: modified version #s")
+                        versions = "pkg-server %s-nasty\n" % pkg.VERSION
+                        for op, vers in self.vops.iteritems():
+                                versions += op + " "
+                                verlen = len(vers)
+                                for v in vers:
+                                        # if there are multiple versions,
+                                        # then sometimes leave one out
+                                        if verlen > 1 and \
+                                            random.randint(0, 10) <= 1:
+                                                cherrypy.log(
+                                                    "NASTY versions_0: "
+                                                    "dropped %s/%s" % (op, v))
+                                                verlen -= 1
+                                                continue
+                                        # Periodically increment or
+                                        # decrement the version.
+                                        oldv = v
+                                        v = int(v +
+                                            random.normalvariate(0, 0.8))
+                                        versions += str(v) + " "
+                                        if v != oldv:
+                                                cherrypy.log(
+                                                    "NASTY versions_0: "
+                                                    "Altered %s/%s -> %s/%d" %
+                                                    (op, oldv, op, v))
+                                versions += "\n"
+                        return versions
+
+                versions = "pkg-server %s\n" % pkg.VERSION
+                versions += "\n".join(
+                    "%s %s" % (op, " ".join(str(v) for v in vers))
+                    for op, vers in self.vops.iteritems()
+                ) + "\n"
+                return versions
+
+        # Fire the before handler less often for versions/0; when it
+        # fails everything else comes to a halt.
+        versions_0._cp_config = { "tools.nasty_before.maxroll": 200 }
 
         # Override _cp_config for catalog_0 operation
         def catalog_0(self, *tokens):
@@ -1617,37 +1787,22 @@
                 the requesting client.  Incremental catalogs are not supported
                 for v0 catalog clients."""
 
-                # Response headers have to be setup *outside* of the function
-                # that yields the catalog content.
-                try:
-                        cat = self.repo.get_catalog(pub=self._get_req_pub())
-                except srepo.RepositoryError, e:
-                        cherrypy.log("Request failed: %s" % str(e))
-                        raise cherrypy.HTTPError(httplib.BAD_REQUEST, str(e))
-
-                response = cherrypy.response
-                response.headers["Content-type"] = "text/plain; charset=utf-8"
-                response.headers["Last-Modified"] = \
-                    cat.last_modified.isoformat()
-                response.headers["X-Catalog-Type"] = "full"
-
-                def output():
-                        try:
-                                for l in self.repo.catalog_0(
-                                    pub=self._get_req_pub()):
-                                        yield l
-                        except srepo.RepositoryError, e:
-                                # Can't do anything in a streaming generator
-                                # except log the error and return.
-                                cherrypy.log("Request failed: %s" % str(e))
-                                return
-
-                return output()
+                # We always raise BAD_REQUEST here because v0 catalogs
+                # are toxic to clients who are facing a nasty antagonist--
+                # the client has no way to verify that the content, and
+                # things go badly off the rails.
+                raise cherrypy.HTTPError(httplib.BAD_REQUEST)
 
         catalog_0._cp_config = {
             "response.stream": True,
-            "tools.nasty_httperror.on": True,
-            "tools.nasty_httperror.bonus": 1
+            #
+            # We disable the nasty_before for catalog 0 because clients
+            # who receive a 0 length response for a catalog_0 see that
+            # as a valid but empty catalog.  This causes many issues when
+            # trying to write tests against the nasty depot.  catalog_0
+            # is going away imminently so we don't really care.
+            #
+            "tools.nasty_before.on": False
         }
 
         def manifest_0(self, *tokens):
@@ -1701,30 +1856,20 @@
                         self.requested_manifests.append(fpath)
 
                 # NASTY
-                # Send an error before serving the manifest, perhaps
-                if self.need_nasty():
-                        self.nasty_retryable_error()
-                elif self.need_nasty_infrequently():
-                        # Fall asleep before finishing the request
-                        time.sleep(35)
-                elif self.need_nasty_rarely():
-                        # Forget that the manifest is here
-                        raise cherrypy.HTTPError(httplib.NOT_FOUND)
-
-                # NASTY
                 # Send the wrong manifest
-                if self.need_nasty_rarely():
-                        pick = random.randint(0,
-                            len(self.requested_manifests) - 1)
-                        badpath = self.requested_manifests[pick]
-
+                if self.need_nasty_3():
+                        cherrypy.log("NASTY manifest_0: serve wrong mfst")
+                        badpath = random.choice(self.requested_manifests)
                         return serve_file(badpath, "text/plain; charset=utf-8")
 
                 # NASTY
                 # Call a misbehaving serve_file
                 return self.nasty_serve_file(fpath, "text/plain; charset=utf-8")
 
-        manifest_0._cp_config = { "response.stream": True }
+        manifest_0._cp_config = {
+            "response.stream": True,
+            "tools.nasty_before.maxroll": 200
+        }
 
         def filelist_0(self, *tokens, **params):
                 """Request data contains application/x-www-form-urlencoded
@@ -1735,7 +1880,8 @@
                         self.flist_requests += 1
 
                         # NASTY
-                        if self.need_nasty_occasionally():
+                        if self.need_nasty_2():
+                                cherrypy.log("NASTY filelist_0: empty response")
                                 return
 
                         # Create a dummy file object that hooks to the write()
@@ -1761,10 +1907,6 @@
                         cherrypy.request.hooks.attach("on_end_request",
                             self._tar_stream_close, failsafe=True)
 
-                        # NASTY
-                        if self.need_nasty_infrequently():
-                                time.sleep(35)
-
                         pub = self._get_req_pub()
                         for v in params.values():
 
@@ -1778,15 +1920,19 @@
                                         self.requested_files.append(v)
 
                                 # NASTY
-                                if self.need_nasty_infrequently():
+                                if self.need_nasty_3():
                                         # Give up early
+                                        cherrypy.log(
+                                            "NASTY filelist_0: give up early")
                                         break
-                                elif self.need_nasty_infrequently():
+                                elif self.need_nasty_3():
                                         # Skip this file
+                                        cherrypy.log(
+                                            "NASTY filelist_0: skip a file")
                                         continue
-                                elif self.need_nasty_rarely():
+                                elif self.need_nasty_4():
                                         # Take a nap
-                                        time.sleep(35)
+                                        self.nasty_nap()
 
                                 try:
                                         filepath = self.repo.file(v, pub=pub)
@@ -1796,10 +1942,11 @@
 
                                 # NASTY
                                 # Send a file with the wrong content
-                                if self.need_nasty_rarely():
-                                        pick = random.randint(0,
-                                            len(self.requested_files) - 1)
-                                        badfn = self.requested_files[pick]
+                                if self.need_nasty_4():
+                                        cherrypy.log(
+                                            "NASTY filelist_0: wrong content")
+                                        badfn = \
+                                            random.choice(self.requested_files)
                                         badpath = self.__get_bad_path(badfn)
 
                                         tar_stream.add(badpath, v, False)
@@ -1810,15 +1957,17 @@
 
                         # NASTY
                         # Write garbage into the stream
-                        if self.need_nasty_infrequently():
+                        if self.need_nasty_3():
+                                cherrypy.log(
+                                    "NASTY filelist_0: add stream garbage")
                                 f.write("NASTY!")
 
                         # NASTY
                         # Send an extraneous file
-                        if self.need_nasty_infrequently():
-                                pick = random.randint(0,
-                                    len(self.requested_files) - 1)
-                                extrafn = self.requested_files[pick]
+                        if self.need_nasty_3():
+                                cherrypy.log(
+                                    "NASTY filelist_0: send extra file")
+                                extrafn = random.choice(self.requested_files)
                                 extrapath = self.repo.file(extrafn, pub=pub)
                                 tar_stream.add(extrapath, extrafn, False)
 
@@ -1843,7 +1992,6 @@
         # hooks in is too late.
         filelist_0._cp_config = {
             "response.stream": True,
-            "tools.nasty_httperror.on": True,
             "tools.response_headers.on": True,
             "tools.response_headers.headers": [
                 ("Content-Type", "application/data"),
@@ -1886,21 +2034,16 @@
                         self.requested_files.append(fhash)
 
                 # NASTY
-                # Send an error before serving the file, perhaps
-                if self.need_nasty():
-                        self.nasty_retryable_error()
-                elif self.need_nasty_rarely():
-                        # Fall asleep before finishing the request
-                        time.sleep(35)
-                elif self.need_nasty_rarely():
+                if self.need_nasty_4():
                         # Forget that the file is here
+                        cherrypy.log("NASTY file_0: 404 NOT_FOUND")
                         raise cherrypy.HTTPError(httplib.NOT_FOUND)
 
                 # NASTY
                 # Send the wrong file
-                if self.need_nasty_rarely():
-                        pick = random.randint(0, len(self.requested_files) - 1)
-                        badfn = self.requested_files[pick]
+                if self.need_nasty_4():
+                        cherrypy.log("NASTY file_0: serve wrong file")
+                        badfn = random.choice(self.requested_files)
                         badpath = self.__get_bad_path(badfn)
 
                         return serve_file(badpath, "application/data")
@@ -1911,6 +2054,9 @@
 
         file_0._cp_config = { "response.stream": True }
 
+        # file_1 degenerates to calling file_0 except when publishing, so
+        # there's no need to touch it here.
+
         def catalog_1(self, *tokens):
                 """Outputs the contents of the specified catalog file, using the
                 name in the request path, directly to the client."""
@@ -1940,31 +2086,30 @@
                         self.requested_catalogs.append(fpath)
 
                 # NASTY
-                # Send an error before serving the catalog, perhaps
-                if self.need_nasty():
-                        self.nasty_retryable_error()
-                elif self.need_nasty_rarely():
-                        # Fall asleep before finishing the request
-                        time.sleep(35)
-                elif self.need_nasty_rarely():
-                        # Forget that the catalog is here
-                        raise cherrypy.HTTPError(httplib.NOT_FOUND)
-
-                # NASTY
                 # Send the wrong catalog
-                if self.need_nasty_rarely():
-                        pick = random.randint(0,
-                            len(self.requested_catalogs) - 1)
-                        badpath = self.requested_catalogs[pick]
-
+                if self.need_nasty_3():
+                        cherrypy.log("NASTY catalog_1: wrong catalog file")
+                        badpath = random.choice(self.requested_catalogs)
                         return serve_file(badpath, "text/plain; charset=utf-8")
 
                 # NASTY
-                # Call a misbehaving serve_file
                 return self.nasty_serve_file(fpath, "text/plain; charset=utf-8")
 
-        catalog_1._cp_config = { "response.stream": True }
+        catalog_1._cp_config = {
+            "response.stream": True,
+            "tools.nasty_before.maxroll": 200
+        }
 
+        def search_1(self, *args, **params):
+                # Raise assorted errors; if not, call superclass search_1.
+                if self.need_nasty():
+                        errs = [httplib.NOT_FOUND, httplib.BAD_REQUEST,
+                            httplib.SERVICE_UNAVAILABLE]
+                        code = random.choice(errs)
+                        cherrypy.log("NASTY search_1: HTTP %d" % code)
+                        raise cherrypy.HTTPError(code)
+
+                return DepotHTTP.search_1(self, *args, **params)
 
         def nasty_serve_file(self, filepath, content_type):
                 """A method that imitates the functionality of serve_file(),
@@ -1983,16 +2128,19 @@
 
                 # NASTY
                 # Send incorrect content length
-                if self.need_nasty_rarely():
+                if self.need_nasty_4():
                         response.headers["Content-Length"] = str(filesz +
                                 random.randint(1, 1024))
                         already_nasty = True
                 else:
                         response.headers["Content-Length"] = str(filesz)
 
-                # NASTY
-                # Send truncated file
-                if self.need_nasty_rarely() and not already_nasty:
+                if already_nasty:
+                        response.body = nfile.read(filesz)
+                elif self.need_nasty_3():
+                        # NASTY
+                        # Send truncated file
+                        cherrypy.log("NASTY serve_file: truncated file")
                         response.body = nfile.read(filesz - random.randint(1,
                             filesz - 1))
                         # If we're sending data, lie about the length and
@@ -2000,15 +2148,35 @@
                         if content_type == "application/data":
                                 response.headers["Content-Length"] = str(
                                     len(response.body))
-                elif self.need_nasty_rarely() and not already_nasty:
+                elif self.need_nasty_3():
+                        # NASTY
                         # Write garbage into the response
-                        response.body = nfile.read(filesz)
-                        response.body += "NASTY!"
+                        cherrypy.log("NASTY serve_file: prepend garbage")
+                        response.body = "NASTY!"
+                        response.body += nfile.read(filesz)
                         # If we're sending data, lie about the length and
                         # make the client catch us.
                         if content_type == "application/data":
                                 response.headers["Content-Length"] = str(
                                     len(response.body))
+                elif self.need_nasty_3():
+                        # NASTY
+                        # overwrite some garbage into the response, without
+                        # changing the length.
+                        cherrypy.log("NASTY serve_file: flip bits")
+                        body = nfile.read(filesz)
+                        # pick a low number of bytes to corrupt
+                        ncorrupt = 1 + int(abs(random.gauss(0, 1)))
+                        for x in range(0, ncorrupt):
+                                p = random.randint(0, max(0, filesz - 1))
+                                char = ord(body[p])
+                                # pick a bit to flip; favor low numbers, must
+                                # also cap at bit #7.
+                                bit = min(7, int(abs(random.gauss(0, 3))))
+                                # flip it
+                                char ^= (1 << bit)
+                                body = body[:p] + chr(char) + body[p + 1:]
+                        response.body = body
                 else:
                         response.body = nfile.read(filesz)
 
@@ -2161,7 +2329,7 @@
         # Priority must be higher than the Daemonizer plugin to avoid threads
         # starting before fork().  Daemonizer has a priority of 65, as noted
         # at this URI: http://www.cherrypy.org/wiki/BuiltinPlugins
-        start.priority = 66 
+        start.priority = 66
 
         def stop(self):
                 """Stop the background task plugin."""
@@ -2246,6 +2414,10 @@
                 cfg.PropertySection("pkg_secure", [
                     cfg.PropDefined("ssl_key_passphrase"),
                 ]),
+                cfg.PropertySection("nasty", [
+                    cfg.PropInt("nasty_level"),
+                    cfg.PropInt("nasty_sleep", default=35)
+                ]),
             ],
         }
 
--- a/src/modules/server/face.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/server/face.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 
 #
-# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 """face - provides the BUI (Browser User Interface) for the image packaging
@@ -61,10 +61,11 @@
                     "No update history; unable to generate feed.")
         return pkg.server.feed.handle(depot, request, response, pub)
 
-def __render_template(depot, request, path, pub):
+def __render_template(depot, request, path, pub, http_depot=None):
         template = tlookup.get_template(path)
         base = api.BaseInterface(request, depot, pub)
-        return template.render_unicode(g_vars={ "base": base, "pub": pub })
+        return template.render_unicode(g_vars={ "base": base, "pub": pub,
+            "http_depot": http_depot})
 
 def __handle_error(path, error):
         # All errors are treated as a 404 since reverse proxies such as Apache
@@ -76,7 +77,10 @@
 
         raise cherrypy.NotFound()
 
-def respond(depot, request, response, pub):
+def respond(depot, request, response, pub, http_depot=None):
+        """'http_depot' if set should be the resource that points to the top
+        level of repository being served (referred to as the repo_prefix in
+        depot_index.py)"""
         path = request.path_info.strip("/")
         if pub and os.path.exists(os.path.join(depot.web_root, pub)):
                 # If an item exists under the web root
@@ -119,7 +123,7 @@
                 response.headers.update({ "Expires": 0, "Pragma": "no-cache",
                     "Cache-Control": "no-cache, no-transform, must-revalidate"
                     })
-                return __render_template(depot, request, path, pub)
+                return __render_template(depot, request, path, pub, http_depot)
         except sae.VersionException, e:
                 # The user shouldn't see why we can't render a template, but
                 # the reason should be logged (cleanly).
--- a/src/modules/server/transaction.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/modules/server/transaction.py	Wed Aug 14 11:12:35 2013 +0530
@@ -551,14 +551,16 @@
                         raise TransactionOperationError(_("A package may not "
                             " be marked for both obsoletion and renaming."))
                 elif self.obsolete and action.name not in ("set", "signature"):
-                        raise TransactionOperationError(_("A '%s' action cannot"
-                            " be present in an obsolete package: %s") %
-                            (action.name, action))
+                        raise TransactionOperationError(_("A '%(type)s' action "
+                            "cannot be present in an obsolete package: "
+                            "%(action)s") %
+                            {"type": action.name, "action": action})
                 elif self.renamed and action.name not in \
                     ("depend", "set", "signature"):
-                        raise TransactionOperationError(_("A '%s' action cannot"
-                            " be present in a renamed package: %s") %
-                            (action.name, action))
+                        raise TransactionOperationError(_("A '%(type)s' action "
+                            "cannot be present in a renamed package: "
+                            "%(action)s") %
+                            {"type": action.name, "action": action})
 
                 # Now that the action is known to be sane, we can add it to the
                 # manifest.
--- a/src/packagemanager.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/packagemanager.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 NOTEBOOK_PACKAGE_LIST_PAGE = 0            # Main Package List page index
@@ -4957,11 +4957,13 @@
                 elif option in ("-i", "--info-install"):
                         info_install_arg = argument
 
+        provided_image_dir = True
         if image_dir == None:
-                try:
-                        image_dir = os.environ["PKG_IMAGE"]
-                except KeyError:
-                        image_dir = "/"
+                image_dir, provided_image_dir = api.get_default_image_root()
+
+        if not provided_image_dir:
+                print _("Unable to get the image directory")
+                sys.exit(1)
 
         try:
                 gtk.init_check()
--- a/src/pkg/Makefile	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/Makefile	Wed Aug 14 11:12:35 2013 +0530
@@ -53,7 +53,7 @@
 # necessary after we stop publishing duplicate packages.
 MANIFESTS.cmd     = \
 	cd manifests; \
-	buildnum=$(BUILDNUM); \
+	buildnum=$(BUILDID); \
 	m=$$($(PKGMOGRIFY) -O /dev/null *.p5m ../transforms/nopublish); \
 	echo "$$m" | while read name build; do \
 		[[ $$build -ge $${buildnum%%.*} ]] && echo $$name; \
@@ -70,6 +70,7 @@
 	    PYTHONPATH=$(PKGROOT)/usr/lib/python2.6/vendor-packages
 PKG               = $(PKGCMDENV) pkg
 PKGDEPEND         = $(PKGCMDENV) pkgdepend
+PKGFMT            = $(PKGCMDENV) pkgfmt
 PKGLINT           = $(PKGCMDENV) pkglint
 PKGMOGRIFY        = $(PKGCMDENV) pkgmogrify
 PKGREPO           = $(PKGCMDENV) pkgrepo
@@ -115,6 +116,9 @@
 clobber: clean
 	rm -rf $(PKGDEST) Makefile.link
 
+pkgfmt:
+	$(PKGFMT) -c manifests/*.p5m
+
 # Pass SVr4 package production off to its own makefile
 svr4:
 	$(MAKE) -f Makefile.svr4 _svr4
@@ -123,7 +127,7 @@
 	mkdir -p $@
 
 # Finalize the repository
-repository-metadata: publish-pkgs
+repository-metadata: pkgfmt publish-pkgs
 	$(PKGREPO) -s $(PKGDEST)/repo refresh
 
 publish-pkgs: $(PKGDEST)/repo .WAIT $(PUBLIFESTS)
--- a/src/pkg/external_deps.txt	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/external_deps.txt	Wed Aug 14 11:12:35 2013 +0530
@@ -39,9 +39,12 @@
     pkg:/system/library
     pkg:/system/library/dbus
     pkg:/system/library/math
+    pkg:/system/library/security/crypto
     pkg:/system/linker
     pkg:/system/locale/extra
     pkg:/system/network
+    pkg:/text/gnu-diffutils
+    pkg:/text/gnu-gettext
     pkg:/text/gnu-grep
     pkg:/text/locale
     pkg:/text/tidy
--- a/src/pkg/manifests/SUNWipkg-gui-data.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-set name=pkg.fmri value=pkg:/[email protected],5.11-0.130
-set name=pkg.obsolete value=true
-set name=nopublish.after value=130
--- a/src/pkg/manifests/SUNWipkg-gui-l10n.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-set name=pkg.fmri value=pkg:/[email protected],5.11-0.130
-set name=pkg.obsolete value=true
-set name=nopublish.after value=130
--- a/src/pkg/manifests/SUNWipkg-gui.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/SUNWipkg-gui.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,10 +18,12 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+#
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/[email protected],5.11-0.133
 set name=pkg.renamed value=true
-set name=nopublish.after value=133
+set name=nopublish.after value=0
 depend type=require fmri=package/pkg/[email protected]
--- a/src/pkg/manifests/SUNWipkg-um.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/SUNWipkg-um.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,10 +18,12 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+#
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/[email protected],5.11-0.133
 set name=pkg.renamed value=true
-set name=nopublish.after value=133
+set name=nopublish.after value=0
 depend type=require fmri=package/pkg/[email protected]
--- a/src/pkg/manifests/SUNWipkg.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/SUNWipkg.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,10 +18,12 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+#
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/[email protected],5.11-0.133
 set name=pkg.renamed value=true
-set name=nopublish.after value=133
+set name=nopublish.after value=0
 depend type=require fmri=package/[email protected]
--- a/src/pkg/manifests/amp.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/amp.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -20,10 +20,10 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/[email protected],5.11-0.133
 set name=pkg.renamed value=true
-set name=nopublish.after value=133
+set name=nopublish.after value=0
 depend type=require fmri=web/[email protected]
--- a/src/pkg/manifests/developer:gnu.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/developer:gnu.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -20,10 +20,10 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/developer/[email protected],5.11-0.174.0.0.0.0.0
 set name=pkg.renamed value=true
-set name=nopublish.after value=174
+set name=nopublish.after value=0
 depend type=require fmri=group/feature/[email protected]
--- a/src/pkg/manifests/developer:opensolaris:pkg5.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/developer:opensolaris:pkg5.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/developer/opensolaris/pkg5@$(PKGVERS)
@@ -49,6 +49,8 @@
 depend type=require fmri=pkg:/system/header
 depend type=require fmri=pkg:/system/linker
 depend type=require fmri=pkg:/system/locale/extra
+depend type=require fmri=pkg:/text/gnu-diffutils
+depend type=require fmri=pkg:/text/gnu-gettext
 depend type=require fmri=pkg:/text/locale
 depend type=require fmri=pkg:/text/tidy
 depend type=require fmri=pkg:/web/server/apache-22
--- a/src/pkg/manifests/gcc-dev.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/gcc-dev.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -20,10 +20,10 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/[email protected],5.11-0.133
 set name=pkg.renamed value=true
-set name=nopublish.after value=133
+set name=nopublish.after value=0
 depend type=require fmri=developer/[email protected]
--- a/src/pkg/manifests/package:pkg.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/package:pkg.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,13 +18,13 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/package/pkg@$(PKGVERS)
 set name=pkg.summary value="Image Packaging System"
 set name=pkg.description \
-    value="The Image Packaging System (IPS), or pkg(5), is the software delivery system used on Oracle Solaris.  This package contains the core command-line components and depot server."
+    value="The Image Packaging System (IPS), or pkg(5), is the software delivery system used on Oracle Solaris.  This package contains the core command-line components and pkg.depotd server."
 set name=info.classification \
     value=org.opensolaris.category.2008:System/Packaging
 set name=variant.arch value=$(ARCH)
@@ -85,6 +85,7 @@
 #
 file path=$(PYDIRVP)/pkg/client/bootenv.py pkg.depend.bypass-generate=.*libbe.*
 file path=$(PYDIRVP)/pkg/client/debugvalues.py
+file path=$(PYDIRVP)/pkg/client/firmware.py
 file path=$(PYDIRVP)/pkg/client/history.py
 file path=$(PYDIRVP)/pkg/client/image.py
 file path=$(PYDIRVP)/pkg/client/imageconfig.py
@@ -96,6 +97,7 @@
 file path=$(PYDIRVP)/pkg/client/linkedimage/common.py
 file path=$(PYDIRVP)/pkg/client/linkedimage/system.py
 file path=$(PYDIRVP)/pkg/client/linkedimage/zone.py
+file path=$(PYDIRVP)/pkg/client/options.py
 file path=$(PYDIRVP)/pkg/client/pkg_solver.py
 file path=$(PYDIRVP)/pkg/client/pkgdefs.py
 file path=$(PYDIRVP)/pkg/client/pkgplan.py
@@ -203,15 +205,23 @@
 file path=etc/security/auth_attr.d/package:pkg
 dir  path=etc/security/exec_attr.d
 file path=etc/security/exec_attr.d/package:pkg
+dir  path=etc/user_attr.d
+file path=etc/user_attr.d/package:pkg
 dir  path=lib
 dir  path=lib/svc
 dir  path=lib/svc/manifest
 dir  path=lib/svc/manifest/application
 file path=lib/svc/manifest/application/pkg/pkg-mdns.xml
+file path=lib/svc/manifest/application/pkg/pkg-mirror.xml
+file path=lib/svc/manifest/application/pkg/pkg-repositories-setup.xml
 file path=lib/svc/manifest/application/pkg/pkg-server.xml
 dir  path=lib/svc/method
-file path=lib/svc/method/svc-pkg-depot
 file path=lib/svc/method/svc-pkg-mdns
+file path=lib/svc/method/svc-pkg-mirror
+file path=lib/svc/method/svc-pkg-repositories-setup
+file path=lib/svc/method/svc-pkg-server
+dir  path=lib/svc/share
+file path=lib/svc/share/pkg5_include.sh
 dir  path=usr
 dir  path=usr/bin
 file path=usr/bin/pkg
@@ -225,6 +235,7 @@
 file path=usr/bin/pkgrepo
 file path=usr/bin/pkgsend
 file path=usr/bin/pkgsign
+file path=usr/bin/pkgsurf
 dir  path=usr/lib
 file path=usr/lib/pkg.depotd mode=0755
 dir  path=usr/share
@@ -297,6 +308,70 @@
 file path=usr/share/lib/pkg/web/index.shtml
 file path=usr/share/lib/pkg/web/robots.txt
 file path=usr/share/lib/pkg/web/shared.shtml
+dir  path=usr/share/locale
+dir  path=usr/share/locale/ar
+dir  path=usr/share/locale/ar/LC_MESSAGES
+file path=usr/share/locale/ar/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/ca
+dir  path=usr/share/locale/ca/LC_MESSAGES
+file path=usr/share/locale/ca/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/cs
+dir  path=usr/share/locale/cs/LC_MESSAGES
+file path=usr/share/locale/cs/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/de
+dir  path=usr/share/locale/de/LC_MESSAGES
+file path=usr/share/locale/de/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/es
+dir  path=usr/share/locale/es/LC_MESSAGES
+file path=usr/share/locale/es/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/fr
+dir  path=usr/share/locale/fr/LC_MESSAGES
+file path=usr/share/locale/fr/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/he
+dir  path=usr/share/locale/he/LC_MESSAGES
+file path=usr/share/locale/he/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/hu
+dir  path=usr/share/locale/hu/LC_MESSAGES
+file path=usr/share/locale/hu/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/id
+dir  path=usr/share/locale/id/LC_MESSAGES
+file path=usr/share/locale/id/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/it
+dir  path=usr/share/locale/it/LC_MESSAGES
+file path=usr/share/locale/it/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/ja
+dir  path=usr/share/locale/ja/LC_MESSAGES
+file path=usr/share/locale/ja/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/ko
+dir  path=usr/share/locale/ko/LC_MESSAGES
+file path=usr/share/locale/ko/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/nl
+dir  path=usr/share/locale/nl/LC_MESSAGES
+file path=usr/share/locale/nl/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/pl
+dir  path=usr/share/locale/pl/LC_MESSAGES
+file path=usr/share/locale/pl/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/pt_BR
+dir  path=usr/share/locale/pt_BR/LC_MESSAGES
+file path=usr/share/locale/pt_BR/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/ru
+dir  path=usr/share/locale/ru/LC_MESSAGES
+file path=usr/share/locale/ru/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/sk
+dir  path=usr/share/locale/sk/LC_MESSAGES
+file path=usr/share/locale/sk/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/sv
+dir  path=usr/share/locale/sv/LC_MESSAGES
+file path=usr/share/locale/sv/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/zh_CN
+dir  path=usr/share/locale/zh_CN/LC_MESSAGES
+file path=usr/share/locale/zh_CN/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/zh_HK
+dir  path=usr/share/locale/zh_HK/LC_MESSAGES
+file path=usr/share/locale/zh_HK/LC_MESSAGES/pkg.mo
+dir  path=usr/share/locale/zh_TW
+dir  path=usr/share/locale/zh_TW/LC_MESSAGES
+file path=usr/share/locale/zh_TW/LC_MESSAGES/pkg.mo
 dir  path=usr/share/man
 dir  path=usr/share/man/ja_JP.UTF-8
 dir  path=usr/share/man/ja_JP.UTF-8/man1
@@ -327,6 +402,7 @@
 file path=usr/share/man/man1/pkgrepo.1
 file path=usr/share/man/man1/pkgsend.1
 file path=usr/share/man/man1/pkgsign.1
+file path=usr/share/man/man1/pkgsurf.1
 dir  path=usr/share/man/man1m
 file path=usr/share/man/man1m/pkg.depotd.1m
 dir  path=usr/share/man/man5
@@ -354,8 +430,11 @@
 file path=usr/share/pkg/transforms/documentation
 file path=usr/share/pkg/transforms/locale
 file path=usr/share/pkg/transforms/smf-manifests
+dir  path=var/cache/pkg/mirror
+dir  path=var/log/pkg/mirror
 group groupname=pkg5srv gid=97
-user username=pkg5srv gcos-field="pkg(5) server UID" group=pkg5srv uid=97
+user username=pkg5srv gcos-field="pkg(5) server UID" group=pkg5srv password=NP \
+    uid=97
 legacy pkg=SUNWipkg version=0.0.0
 license cr_Oracle license=cr_Oracle
 license lic_gustaebel license=lic_gustaebel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/manifests/package:pkg:depot.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,69 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+set name=pkg.fmri value=pkg:/package/pkg/depot@$(PKGVERS)
+set name=pkg.summary value="IPS Depot"
+set name=pkg.description \
+    value="A service that provides a scalable web-based pkg(5) server."
+set name=info.classification \
+    value=org.opensolaris.category.2008:System/Packaging
+set name=variant.arch value=$(ARCH)
+dir  path=etc
+dir  path=etc/pkg
+dir  path=etc/pkg/depot
+dir  path=etc/pkg/depot/conf.d
+file path=etc/pkg/depot/depot.conf.mako
+file path=etc/pkg/depot/depot_httpd.conf.mako
+file path=etc/pkg/depot/depot_index.py pkg.tmp.autopyc=false
+dir  path=lib
+dir  path=lib/svc
+dir  path=lib/svc/manifest
+dir  path=lib/svc/manifest/application
+dir  path=lib/svc/manifest/application/pkg
+file path=lib/svc/manifest/application/pkg/pkg-depot.xml
+file path=lib/svc/method/svc-pkg-depot
+dir  path=usr
+file path=usr/lib/pkg.depot-config mode=0755
+dir  path=usr/share/lib/pkg/web
+file path=usr/share/lib/pkg/web/repos.shtml
+dir  path=usr/share/man/man1m
+file path=usr/share/man/man1m/pkg.depot-config.1m
+dir  path=var
+dir  path=var/cache
+dir  path=var/cache/pkg owner=pkg5srv
+dir  path=var/cache/pkg/depot owner=pkg5srv
+dir  path=var/log
+dir  path=var/log/pkg
+dir  path=var/log/pkg/depot owner=pkg5srv
+# we deliver 0-byte log file stubs
+file path=var/log/pkg/depot/access_log owner=pkg5srv mode=0644 preserve=true
+file path=var/log/pkg/depot/error_log owner=pkg5srv mode=0644 preserve=true
+file path=var/log/pkg/depot/rewrite.log owner=pkg5srv mode=0644 preserve=true
+license cr_Oracle license=cr_Oracle
+#
+# The manual dependency on apache results from our calling apachectl from
+# our method script, and can't be detected by pkgdepend.
+#
+depend type=require fmri=web/server/apache-22
+# p5p support in the system repository requires mod_wsgi
+depend type=require fmri=web/server/apache-22/module/apache-wsgi-26
--- a/src/pkg/manifests/package:pkg:package-manager.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/package:pkg:package-manager.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/package/pkg/package-manager@$(PKGVERS)
@@ -132,70 +132,6 @@
 file path=usr/share/icons/hicolor/48x48/apps/packagemanager.png
 dir  path=usr/share/icons/hicolor/48x48/mimetypes
 file path=usr/share/icons/hicolor/48x48/mimetypes/gnome-mime-application-vnd.pkg5.info.png
-dir  path=usr/share/locale
-dir  path=usr/share/locale/ar
-dir  path=usr/share/locale/ar/LC_MESSAGES
-file path=usr/share/locale/ar/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/ca
-dir  path=usr/share/locale/ca/LC_MESSAGES
-file path=usr/share/locale/ca/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/cs
-dir  path=usr/share/locale/cs/LC_MESSAGES
-file path=usr/share/locale/cs/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/de
-dir  path=usr/share/locale/de/LC_MESSAGES
-file path=usr/share/locale/de/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/es
-dir  path=usr/share/locale/es/LC_MESSAGES
-file path=usr/share/locale/es/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/fr
-dir  path=usr/share/locale/fr/LC_MESSAGES
-file path=usr/share/locale/fr/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/he
-dir  path=usr/share/locale/he/LC_MESSAGES
-file path=usr/share/locale/he/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/hu
-dir  path=usr/share/locale/hu/LC_MESSAGES
-file path=usr/share/locale/hu/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/id
-dir  path=usr/share/locale/id/LC_MESSAGES
-file path=usr/share/locale/id/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/it
-dir  path=usr/share/locale/it/LC_MESSAGES
-file path=usr/share/locale/it/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/ja
-dir  path=usr/share/locale/ja/LC_MESSAGES
-file path=usr/share/locale/ja/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/ko
-dir  path=usr/share/locale/ko/LC_MESSAGES
-file path=usr/share/locale/ko/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/nl
-dir  path=usr/share/locale/nl/LC_MESSAGES
-file path=usr/share/locale/nl/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/pl
-dir  path=usr/share/locale/pl/LC_MESSAGES
-file path=usr/share/locale/pl/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/pt_BR
-dir  path=usr/share/locale/pt_BR/LC_MESSAGES
-file path=usr/share/locale/pt_BR/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/ru
-dir  path=usr/share/locale/ru/LC_MESSAGES
-file path=usr/share/locale/ru/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/sk
-dir  path=usr/share/locale/sk/LC_MESSAGES
-file path=usr/share/locale/sk/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/sv
-dir  path=usr/share/locale/sv/LC_MESSAGES
-file path=usr/share/locale/sv/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/zh_CN
-dir  path=usr/share/locale/zh_CN/LC_MESSAGES
-file path=usr/share/locale/zh_CN/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/zh_HK
-dir  path=usr/share/locale/zh_HK/LC_MESSAGES
-file path=usr/share/locale/zh_HK/LC_MESSAGES/pkg.mo
-dir  path=usr/share/locale/zh_TW
-dir  path=usr/share/locale/zh_TW/LC_MESSAGES
-file path=usr/share/locale/zh_TW/LC_MESSAGES/pkg.mo
 dir  path=usr/share/man
 dir  path=usr/share/man/ja_JP.UTF-8
 dir  path=usr/share/man/ja_JP.UTF-8/man1
--- a/src/pkg/manifests/package:pkg:system-repository.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/package:pkg:system-repository.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -55,10 +55,11 @@
 dir  path=var/cache/pkg/sysrepo owner=pkg5srv
 dir  path=var/log
 dir  path=var/log/pkg
-dir  path=var/log/pkg/sysrepo
+dir  path=var/log/pkg/sysrepo owner=pkg5srv
 # we deliver 0-byte log file stubs
-file path=var/log/pkg/sysrepo/access_log preserve=renamenew
-file path=var/log/pkg/sysrepo/error_log preserve=renamenew
+file path=var/log/pkg/sysrepo/access_log owner=pkg5srv mode=0644 preserve=true
+file path=var/log/pkg/sysrepo/error_log owner=pkg5srv mode=0644 preserve=true
+file path=var/log/pkg/sysrepo/rewrite.log owner=pkg5srv mode=0644 preserve=true
 license cr_Oracle license=cr_Oracle
 #
 # The manual dependency on apache results from our calling apachectl from
--- a/src/pkg/manifests/package:pkg:update-manager.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/package:pkg:update-manager.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/package/pkg/update-manager@$(PKGVERS)
@@ -42,7 +42,7 @@
 dir  path=lib/svc/manifest/application/pkg
 file path=lib/svc/manifest/application/pkg/pkg-update.xml
 dir  path=lib/svc/method
-file path=lib/svc/method/pkg-update
+file path=lib/svc/method/svc-pkg-update
 dir  path=usr
 dir  path=usr/bin
 file path=usr/bin/pm-updatemanager
--- a/src/pkg/manifests/system:trusted:trusted-nonglobal.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/system:trusted:trusted-nonglobal.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -18,10 +18,12 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+
+#
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/system/trusted/[email protected],5.11-0.166
 set name=pkg.renamed value=true
-set name=nopublish.after value=166
+set name=nopublish.after value=0
 depend type=require fmri=pkg:/group/feature/trusted-desktop
--- a/src/pkg/manifests/web:amp.p5m	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/manifests/web:amp.p5m	Wed Aug 14 11:12:35 2013 +0530
@@ -20,10 +20,10 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/web/[email protected],5.11-0.174.0.0.0.0.0
 set name=pkg.renamed value=true
-set name=nopublish.after value=174
+set name=nopublish.after value=0
 depend type=require fmri=group/feature/[email protected]
--- a/src/pkg/transforms/defaults	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkg/transforms/defaults	Wed Aug 14 11:12:35 2013 +0530
@@ -18,14 +18,18 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013 Oracle and/or its affiliates. All rights reserved.
 #
 
 # Set some specific permissions
 <transform dir path=(etc|usr|var)$ -> set group sys>
-<transform dir path=etc/(brand|gconf|pkg|zones)$ -> set group sys>
+<transform dir path=etc/(brand|gconf|pkg|user_attr.d|zones)$ -> set group sys>
 <transform dir path=var/log$ -> set group sys>
+<transform dir path=var/log/pkg/mirror -> set group pkg5srv>
+<transform dir path=var/log/pkg/mirror -> set owner pkg5srv>
 <transform dir path=var/cache$ -> set group bin>
+<transform dir path=var/cache/pkg/mirror -> set group pkg5srv>
+<transform dir path=var/cache/pkg/mirror -> set owner pkg5srv>
 <transform dir file path=etc/gconf/schemas -> set group sys>
 <transform dir file path=etc/(security|xdg) -> set group sys>
 <transform dir path=usr/share$ -> set group sys>
@@ -102,11 +106,11 @@
 
 # only set the info.repository-* values for packages we're responsible for
 <transform pkg pkg.fmri=pkg:/package/.* -> default info.repository-changeset $(CHANGESET)>
-<transform pkg pkg.fmri=pkg:/package/.* -> default info.repository-url ssh://hg.opensolaris.org/hg/pkg/gate>
+<transform pkg pkg.fmri=pkg:/package/.* -> default info.repository-url https://hg.java.net/hg/ips~pkg-gate>
 <transform pkg pkg.fmri=pkg:/system/zones.*-> default info.repository-changeset $(CHANGESET)>
-<transform pkg pkg.fmri=pkg:/system/zones.* -> default info.repository-url ssh://hg.opensolaris.org/hg/pkg/gate>
+<transform pkg pkg.fmri=pkg:/system/zones.* -> default info.repository-url https://hg.java.net/hg/ips~pkg-gate>
 <transform pkg pkg.fmri=pkg:/developer/opensolaris/pkg5 -> default info.repository-changeset $(CHANGESET)>
-<transform pkg pkg.fmri=pkg:/developer/opensolaris/pkg5 -> default info.repository-url ssh://hg.opensolaris.org/hg/pkg/gate>
+<transform pkg pkg.fmri=pkg:/developer/opensolaris/pkg5 -> default info.repository-url https://hg.java.net/hg/ips~pkg-gate>
 # now emit those values
 <transform pkg info.repository-changeset=(.*) -> emit set name=info.repository-changeset value=%<1>>
 <transform pkg info.repository-url=(.*) -> emit set name=info.repository-url value=%<1>>
--- a/src/pkgdep.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkgdep.py	Wed Aug 14 11:12:35 2013 +0530
@@ -43,7 +43,7 @@
 import pkg.publish.dependencies as dependencies
 from pkg.misc import msg, emsg, PipeError
 
-CLIENT_API_VERSION = 73
+CLIENT_API_VERSION = 75
 PKG_CLIENT_NAME = "pkgdepend"
 
 DEFAULT_SUFFIX = ".res"
@@ -489,8 +489,13 @@
                 try:
                         os.makedirs(out_dir)
                 except EnvironmentError, e:
-                        emsg(_("Out dir %s does not exist and could not be "
-                            "created. Error is: %s") % e)
+                        e_dic = {"dir": out_dir}
+                        if len(e.args) > 0:
+                                e_dic["err"] = e.args[1]
+                        else:
+                                e_dic["err"] = e.args[0]
+                        emsg(_("Out dir %(out_dir)s does not exist and could "
+                            "not be created. Error is: %(err)s") % e_dic)
                         return 1
         if suffix and suffix[0] != ".":
                 suffix = "." + suffix
--- a/src/pkgrepo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pkgrepo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -55,6 +55,7 @@
 import warnings
 
 from pkg.client import global_settings
+from pkg.client.debugvalues import DebugValues
 from pkg.misc import msg, PipeError
 import pkg
 import pkg.catalog
@@ -134,20 +135,20 @@
 
      pkgrepo add-publisher -s repo_uri_or_path publisher ...
 
-     pkgrepo get [-F format] [-p publisher ...] -s repo_uri_or_path
-         [section/property ...]
+     pkgrepo get [-F format] [-p publisher ...] -s repo_uri_or_path 
+         [--key ssl_key ... --cert ssl_cert ...] [section/property ...]
 
-     pkgrepo info [-F format] [-H] [-p publisher ...]
-         -s repo_uri_or_path
+     pkgrepo info [-F format] [-H] [-p publisher ...] -s repo_uri_or_path
+         [--key ssl_key ... --cert ssl_cert ...]
 
-     pkgrepo list [-F format] [-H] [-p publisher ...] -s repo_uri_or_path
-         [pkg_fmri_pattern ...]
+     pkgrepo list [-F format] [-H] [-p publisher ...] -s repo_uri_or_path 
+         [--key ssl_key ... --cert ssl_cert ...] [pkg_fmri_pattern ...]
 
-     pkgrepo rebuild [-p publisher ...] -s repo_uri_or_path
-         [--no-catalog] [--no-index]
+     pkgrepo rebuild [-p publisher ...] -s repo_uri_or_path [--key ssl_key ...
+         --cert ssl_cert ...] [--no-catalog] [--no-index]
 
-     pkgrepo refresh [-p publisher ...] -s repo_uri_or_path
-         [--no-catalog] [--no-index]
+     pkgrepo refresh [-p publisher ...] -s repo_uri_or_path [--key ssl_key ...
+         --cert ssl_cert ...] [--no-catalog] [--no-index]
 
      pkgrepo remove [-n] [-p publisher ...] -s repo_uri_or_path
          pkg_fmri_pattern ...
@@ -261,7 +262,8 @@
         return sr.Repository(read_only=read_only, root=path)
 
 
-def setup_transport(conf, subcommand=None, verbose=False):
+def setup_transport(conf, subcommand=None, verbose=False, ssl_key=None,
+    ssl_cert=None):
         repo_uri = conf.get("repo_uri", None)
         if not repo_uri:
                 usage(_("No repository location specified."), cmd=subcommand)
@@ -284,7 +286,7 @@
 
         # Configure target publisher.
         src_pub = transport.setup_publisher(str(repo_uri), "target", xport,
-            xport_cfg, remote_prefix=True)
+            xport_cfg, remote_prefix=True, ssl_key=ssl_key, ssl_cert=ssl_cert)
 
         return xport, src_pub, tmp_dir
 
@@ -398,8 +400,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         out_format = arg
@@ -415,12 +419,17 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         # Setup transport so configuration can be retrieved.
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         # Get properties.
         if pubs:
@@ -660,8 +669,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         if arg not in LISTING_FORMATS:
@@ -677,6 +688,10 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -685,7 +700,8 @@
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         # Retrieve repository status information.
         stat_idx = xport.get_status(xpub)
@@ -760,8 +776,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         out_format = arg
@@ -777,12 +795,18 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
+
 
         # Setup transport so configuration can be retrieved.
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub, out_format=out_format, use_transport=True)
@@ -914,8 +938,11 @@
         subcommand = "rebuild"
         build_catalog = True
         build_index = True
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index"])
+        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index",
+            "key=", "cert="])
         pubs = set()
         for opt, arg in opts:
                 if opt == "-p":
@@ -929,6 +956,10 @@
                         build_catalog = False
                 elif opt == "--no-index":
                         build_index = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -950,7 +981,8 @@
                 elif build_index:
                         xport.publish_rebuild_indexes(xpub)
 
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub)
         if rval == EXIT_OOPS:
@@ -970,8 +1002,11 @@
         subcommand = "refresh"
         add_content = True
         refresh_index = True
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index"])
+        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index",
+            "key=", "cert="])
         pubs = set()
         for opt, arg in opts:
                 if opt == "-p":
@@ -985,6 +1020,10 @@
                         add_content = False
                 elif opt == "--no-index":
                         refresh_index = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -1006,7 +1045,8 @@
                 elif refresh_index:
                         xport.publish_refresh_indexes(xpub)
 
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub)
         if rval == EXIT_OOPS:
@@ -1446,8 +1486,8 @@
         global_settings.client_name = PKG_CLIENT_NAME
 
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "s:?",
-                    ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?",
+                    ["help", "debug="])
         except getopt.GetoptError, e:
                 usage(_("illegal global option -- %s") % e.opt)
 
@@ -1458,6 +1498,14 @@
                         conf["repo_uri"] = parse_uri(arg)
                 elif opt in ("--help", "-?"):
                         show_usage = True
+                elif opt == "-D" or opt == "--debug":
+                        try:
+                                key, value = arg.split("=", 1)
+                        except (AttributeError, ValueError):
+                                usage(_("%(opt)s takes argument of form "
+                                   "name=value, not %(arg)s") % {
+                                   "opt":  opt, "arg": arg })
+                        DebugValues.set_value(key, value)
 
         subcommand = None
         if pargs:
--- a/src/po/POTFILES.in	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/po/POTFILES.in	Wed Aug 14 11:12:35 2013 +0530
@@ -2,6 +2,7 @@
 # Please keep this file in alphabetical order.
 [encoding: UTF-8]
 client.py
+depot-config.py
 depot.py
 gui/data/addmoresoftware.desktop.in
 gui/data/l10n.py
@@ -29,12 +30,15 @@
 modules/client/api.py
 modules/client/api_errors.py
 modules/client/bootenv.py
+modules/client/firmware.py
 modules/client/history.py
 modules/client/image.py
 modules/client/imageconfig.py
 modules/client/imageplan.py
 modules/client/linkedimage/__init__.py
+modules/client/options.py
 modules/client/pkg_solver.py
+modules/client/plandesc.py
 modules/client/progress.py
 modules/client/publisher.py
 modules/client/transport/repo.py
@@ -103,3 +107,4 @@
 util/publish/pkglint.py
 util/publish/pkgmerge.py
 util/publish/pkgmogrify.py
+util/publish/pkgsurf.py
--- a/src/publish.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/publish.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import fnmatch
@@ -85,7 +85,8 @@
 Packager subcommands:
         pkgsend generate [-T pattern] [--target file] source ...
         pkgsend publish [-b bundle ...] [-d source ...] [-s repo_uri_or_path]
-            [-T pattern] [--no-catalog] [manifest ...]
+            [-T pattern] [--key ssl_key ... --cert ssl_cert ...]
+            [--no-catalog] [manifest ...]
 
 Options:
         --help or -?    display usage message
@@ -296,12 +297,14 @@
         # --no-index is now silently ignored as the publication process no
         # longer builds search indexes automatically.
         opts, pargs = getopt.getopt(fargs, "b:d:s:T:", ["fmri-in-manifest",
-            "no-index", "no-catalog"])
+            "no-index", "no-catalog", "key=", "cert="])
 
         add_to_catalog = True
         basedirs = []
         bundles = []
         timestamp_files = []
+        key = None
+        cert = None
         for opt, arg in opts:
                 if opt == "-b":
                         bundles.append(arg)
@@ -315,6 +318,10 @@
                         timestamp_files.append(arg)
                 elif opt == "--no-catalog":
                         add_to_catalog = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if not repo_uri:
                 usage(_("A destination package repository must be provided "
@@ -359,7 +366,8 @@
                         filename = "???"
                         lineno = "???"
 
-                error(_("File %s line %s: %s") % (filename, lineno, e),
+                error(_("File %(filename)s line %(lineno)s: %(err)s") %
+                    {"filename": filename, "lineno": lineno, "err": e},
                     cmd="publish")
                 return 1
 
@@ -379,7 +387,8 @@
                 error(_("Manifest does not set pkg.fmri"))
                 return 1
 
-        xport, pub = setup_transport_and_pubs(repo_uri)
+        xport, pub = setup_transport_and_pubs(repo_uri, ssl_key=key,
+            ssl_cert=cert)
         t = trans.Transaction(repo_uri, pkg_name=pkg_name,
             xport=xport, pub=pub)
         t.open()
@@ -508,7 +517,8 @@
                         filename = "???"
                         lineno = "???"
 
-                error(_("File %s line %s: %s") % (filename, lineno, e),
+                error(_("File %(filename)s line %(lineno)s: %(err)s") %
+                    {"filename": filename, "lineno": lineno, "err": e},
                     cmd="include")
                 return 1
 
@@ -684,14 +694,16 @@
                 return 1
         return 0
 
-def setup_transport_and_pubs(repo_uri, remote=True):
+def setup_transport_and_pubs(repo_uri, remote=True, ssl_key=None,
+    ssl_cert=None):
 
         if repo_uri.startswith("null:"):
                 return None, None
 
         xport, xport_cfg = transport.setup_transport()
         targ_pub = transport.setup_publisher(repo_uri, "default",
-            xport, xport_cfg, remote_prefix=remote)
+            xport, xport_cfg, remote_prefix=remote, ssl_key=ssl_key,
+            ssl_cert=ssl_cert)
 
         return xport, targ_pub
 
@@ -704,11 +716,11 @@
         show_usage = False
         global_settings.client_name = "pkgsend"
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?", ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?", ["help", "debug="])
                 for opt, arg in opts:
                         if opt == "-s":
                                 repo_uri = arg
-                        elif opt == "-D":
+                        elif opt == "-D" or opt == "--debug":
                                 if arg == "allow-timestamp":
                                         key = arg
                                         value = True
@@ -790,7 +802,8 @@
                 error(e, cmd=subcommand)
                 ret = 1
         except getopt.GetoptError, e:
-                usage(_("illegal %s option -- %s") % (subcommand, e.opt))
+                usage(_("illegal %(cmd)s option -- %(opt)s") % \
+                    {"cmd": subcommand, "opt": e.opt})
 
         return ret
 
--- a/src/pull.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/pull.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import calendar
@@ -43,10 +43,13 @@
 import pkg.manifest as manifest
 import pkg.client.api_errors as apx
 import pkg.client.pkgdefs as pkgdefs
+import pkg.client.publisher as publisher
 import pkg.client.transport.transport as transport
 import pkg.misc as misc
 import pkg.p5p
+import pkg.pkgsubprocess as subprocess
 import pkg.publish.transaction as trans
+import pkg.server.repository as sr
 import pkg.version as version
 
 from pkg.client import global_settings
@@ -92,9 +95,12 @@
         msg(_("""\
 Usage:
         pkgrecv [-s src_uri] [-a] [-d (path|dest_uri)] [-c cache_dir]
-            [-kr] [-m match] [-n] [--raw] [--key keyfile --cert certfile]
+            [-kr] [-m match] [-n] [--raw] [--key src_key --cert src_cert]
+            [--dkey dest_key --dcert dest_cert]
             (fmri|pattern) ...
         pkgrecv [-s src_repo_uri] --newest
+        pkgrecv [-s src_repo_uri] [-d path] [-p publisher ...]
+            [--key src_key --cert src_cert] [-n] --clone
 
 Options:
         -a              Store the retrieved package data in a pkg(5) archive
@@ -119,20 +125,36 @@
                         when republishing.  Should not be used with pkgsend.
 
         -m match        Controls matching behaviour using the following values:
-                            all-timestamps
-                                includes all matching timestamps, not just
-                                latest (implies all-versions)
+                            all-timestamps (default)
+                                includes all matching timestamps (implies
+                                all-versions)
                             all-versions
-                                includes all matching versions, not just latest
+                                includes all matching versions
+                            latest
+                                includes only the latest version of each package
 
         -n              Perform a trial run with no changes made.
 
+        -p publisher    Only clone the given publisher. Can be specified
+                        multiple times. Only valid with --clone.
+
         -r              Recursively evaluates all dependencies for the provided
                         list of packages and adds them to the list.
 
         -s src_repo_uri A URI representing the location of a pkg(5)
                         repository to retrieve package data from.
 
+        --clone         Make an exact copy of the source repository. By default,
+                        the clone operation will only succeed if publishers in 
+                        the  source  repository  are  also  present  in  the
+                        destination.  By using -p, the operation can be limited
+                        to  specific  publishers  which  will  be  added  to the
+                        destination repository if not already present.
+                        Packages in the destination repository which are not in
+                        the source will be removed.
+                        Cloning will leave the destination repository altered in
+                        case of an error.
+
         --newest        List the most recent versions of the packages available
                         from the specified repository and exit.  (All other
                         options except -s will be ignored.)
@@ -145,10 +167,16 @@
                         perhaps by correcting file contents or providing
                         additional package metadata.
 
-        --key keyfile   Specify a client SSL key file to use for pkg retrieval.
+        --key src_key   Specify a client SSL key file to use for pkg retrieval.
+
+        --cert src_cert Specify a client SSL certificate file to use for pkg
+                        retrieval.
 
-        --cert certfile Specify a client SSL certificate file to use for pkg
-                        retrieval.
+        --dkey dest_key Specify a client SSL key file to use for pkg
+                        publication.
+
+        --dcert dest_cert Specify a client SSL certificate file to use for pkg
+                          publication.
 
 Environment:
         PKG_DEST        Destination directory or URI
@@ -308,9 +336,10 @@
                 fmri_list = [sorted(dedup[f], reverse=True)[0] for f in dedup]
         return fmri_list
 
-def fetch_catalog(src_pub, tracker, txport, target_catalog):
+def fetch_catalog(src_pub, tracker, txport, target_catalog,
+    include_updates=False):
         """Fetch the catalog from src_uri.
-	
+
 	target_catalog is a hint about whether this is a destination catalog,
 	which helps the progress tracker render the refresh output properly."""
 
@@ -328,7 +357,8 @@
 
         src_pub.transport = txport
         try:
-                src_pub.refresh(True, True, progtrack=tracker)
+                src_pub.refresh(full_refresh=True, immediate=True,
+                    progtrack=tracker, include_updates=include_updates)
         except apx.TransportError, e:
                 # Assume that a catalog doesn't exist for the target publisher,
                 # and drive on.  If there was an actual failure due to a
@@ -345,7 +375,7 @@
         global archive, cache_dir, download_start, xport, xport_cfg, \
             dest_xport, temp_root, targ_pub, target
 
-        all_timestamps = False
+        all_timestamps = True
         all_versions = False
         dry_run = False
         keep_compressed = False
@@ -357,6 +387,10 @@
         raw = False
         key = None
         cert = None
+        dkey = None
+        dcert = None
+        publishers = []
+        clone = False
 
         temp_root = misc.config_temp_root()
 
@@ -368,8 +402,9 @@
         src_uri = os.environ.get("PKG_SRC", None)
 
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "ac:D:d:hkm:nrs:",
-                    ["cert=", "key=", "newest", "raw"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "ac:D:d:hkm:np:rs:",
+                    ["cert=", "key=", "dcert=", "dkey=", "newest", "raw",
+                    "debug=", "clone"])
         except getopt.GetoptError, e:
                 usage(_("Illegal option -- %s") % e.opt)
 
@@ -378,9 +413,11 @@
                         archive = True
                 elif opt == "-c":
                         cache_dir = arg
+                elif opt == "--clone":
+                        clone = True
                 elif opt == "-d":
                         target = arg
-                elif opt == "-D":
+                elif opt == "-D" or opt == "--debug":
                         if arg in ["plan", "transport"]:
                                 key = arg
                                 value = "True"
@@ -399,12 +436,19 @@
                 elif opt == "-m":
                         if arg == "all-timestamps":
                                 all_timestamps = True
+                                all_versions = False
                         elif arg == "all-versions":
+                                all_timestamps = False
                                 all_versions = True
+                        elif arg == "latest":
+                                all_timestamps = False
+                                all_versions = False
                         else:
                                 usage(_("Illegal option value -- %s") % arg)
                 elif opt == "-n":
                         dry_run = True
+                elif opt == "-p":
+                        publishers.append(arg)
                 elif opt == "-r":
                         recursive = True
                 elif opt == "-s":
@@ -417,6 +461,10 @@
                         key = arg
                 elif opt == "--cert":
                         cert = arg
+                elif opt == "--dkey":
+                        dkey = arg
+                elif opt == "--dcert":
+                        dcert = arg
 
         if not list_newest and not target:
                 usage(_("a destination must be provided"))
@@ -432,6 +480,24 @@
                 # Only clean-up cache dir if implicitly created by pkgrecv.
                 # User's cache-dirs should be preserved
                 tmpdirs.append(cache_dir)
+        else:
+                if clone:
+                        usage(_("--clone can not be used with -c.\n"
+                            "Content will be downloaded directly to the "
+                            "destination repository and re-downloading after a "
+                            "pkgrecv failure will not be required."))
+
+        if clone and raw:
+                usage(_("--clone can not be used with --raw.\n"))
+
+        if clone and archive:
+                usage(_("--clone can not be used with -a.\n"))
+
+        if clone and list_newest:
+                usage(_("--clone can not be used with --newest.\n"))
+
+        if publishers and not clone:
+                usage(_("-p can only be used with --clone.\n"))
 
         incoming_dir = tempfile.mkdtemp(dir=temp_root,
             prefix=global_settings.client_name + "-")
@@ -456,7 +522,11 @@
 
         args = (pargs, target, list_newest, all_versions,
             all_timestamps, keep_compressed, raw, recursive, dry_run,
-            dest_xport_cfg, src_uri)
+            dest_xport_cfg, src_uri, dkey, dcert)
+
+        if clone:
+                args += (publishers,)
+                return clone_repo(*args)
 
         if archive:
                 # Retrieving package data for archival requires a different mode
@@ -519,7 +589,8 @@
         return matches
 
 def archive_pkgs(pargs, target, list_newest, all_versions, all_timestamps,
-    keep_compresed, raw, recursive, dry_run, dest_xport_cfg, src_uri):
+    keep_compresed, raw, recursive, dry_run, dest_xport_cfg, src_uri, dkey,
+    dcert):
         """Retrieve source package data completely and then archive it."""
 
         global cache_dir, download_start, xport, xport_cfg
@@ -667,8 +738,339 @@
                 return pkgdefs.EXIT_OOPS
         return pkgdefs.EXIT_OK
 
+
+def clone_repo(pargs, target, list_newest, all_versions, all_timestamps,
+    keep_compressed, raw, recursive, dry_run, dest_xport_cfg, src_uri, dkey,
+    dcert, publishers):
+
+        global cache_dir, download_start, xport, xport_cfg, dest_xport
+
+        invalid_manifests = []
+        total_processed = 0
+        modified_pubs = set()
+        deleted_pkgs = False
+        old_c_root = None
+        del_search_index = set()
+
+        # Turn target into a valid URI.
+        target = publisher.RepositoryURI(misc.parse_uri(target))
+
+        if target.scheme != "file":
+                abort(err=_("Destination clone repository must be "
+                    "filesystem-based."))
+
+        # Initialize the target repo.
+        try:
+                repo = sr.Repository(read_only=False,
+                    root=target.get_pathname())
+        except sr.RepositoryInvalidError, e:
+                txt = str(e) + "\n\n"
+                txt += _("To create a repository, use the pkgrepo command.")
+                abort(err=txt)
+
+        def copy_catalog(src_cat_root, pub):
+                # Copy catalog files.
+                c_root = repo.get_pub_rstore(pub).catalog_root
+                rstore_root = repo.get_pub_rstore(pub).root
+                try:
+                        # We just use mkdtemp() to find ourselves a directory
+                        # which does not already exist. The created dir is not
+                        # used.
+                        old_c_root = tempfile.mkdtemp(dir=rstore_root,
+                            prefix='catalog-')
+                        shutil.rmtree(old_c_root)
+                        shutil.move(c_root, old_c_root)
+                        shutil.copytree(src_cat_root, c_root)
+                except Exception, e:
+                        abort(err=_("Unable to copy catalog files: %s") % e)
+                return old_c_root
+
+        # Check if all publishers in src are also in target. If not, add
+        # depending on what publishers were specified by user.
+        pubs_to_sync = []
+        pubs_to_add = []
+        src_pubs = {}
+        for sp in xport_cfg.gen_publishers():
+                src_pubs[sp.prefix] = sp
+        dst_pubs = repo.get_publishers()
+
+        pubs_specified = False
+        unknown_pubs = []
+        for p in publishers:
+                if p not in src_pubs and p != '*':
+                        abort(err=_("The publisher %s does not exist in the "
+                            "source repository." % p))
+                pubs_specified = True
+
+        for sp in src_pubs:
+                if sp not in dst_pubs and (sp in publishers or \
+                    '*' in publishers):
+                        pubs_to_add.append(src_pubs[sp])
+                        pubs_to_sync.append(src_pubs[sp])
+                elif sp in dst_pubs and (sp in publishers or '*' in publishers
+                    or not pubs_specified):
+                        pubs_to_sync.append(src_pubs[sp])
+                elif not pubs_specified:
+                        unknown_pubs.append(sp)
+
+        # We only print warning if the user didn't specify any valid publishers 
+        # to add/sync.
+        if len(unknown_pubs):
+                txt = _("\nThe following publishers are present in the "
+                    "source repository but not in the target repository.\n"
+                    "Please use -p to specify which publishers need to be "
+                    "cloned or -p '*' to clone all publishers.")
+                for p in unknown_pubs:
+                        txt += "\n    %s\n" % p
+                abort(err=txt)
+
+        # Create non-existent publishers.
+        for p in pubs_to_add:
+                if not dry_run:
+                        msg(_("Adding publisher %s ...") % p.prefix)
+                        repo.add_publisher(p)
+                else:
+                        msg(_("Adding publisher %s (dry-run) ...") % p.prefix)
+
+        for src_pub in pubs_to_sync:
+                msg(_("Processing packages for publisher %s ...") %
+                    src_pub.prefix)
+                tracker = get_tracker()
+
+                src_basedir = tempfile.mkdtemp(dir=temp_root,
+                    prefix=global_settings.client_name + "-")
+                tmpdirs.append(src_basedir)
+
+                xport_cfg.pkg_root = src_basedir
+
+                # We make the destination repo our cache directory to save on
+                # IOPs. Have to remove all the old caches first.
+                if not dry_run:
+                        xport_cfg.clear_caches(shared=True)
+                        xport_cfg.add_cache(
+                            repo.get_pub_rstore(src_pub.prefix).file_root,
+                            readonly=False)
+
+                # Retrieve src and dest catalog for comparison.
+                src_pub.meta_root = src_basedir
+
+                src_cat = fetch_catalog(src_pub, tracker, xport, False,
+                    include_updates=True)
+                src_cat_root = src_cat.meta_root
+
+                try:
+                        targ_cat = repo.get_catalog(pub=src_pub.prefix)
+                except sr.RepositoryUnknownPublisher:
+                        targ_cat = catalog.Catalog(read_only=True)
+
+                src_fmris = set([x for x in src_cat.fmris(last=False)])
+                targ_fmris = set([x for x in targ_cat.fmris(last=False)])
+
+                del src_cat
+                del targ_cat
+
+                to_add = []
+                to_rm = []
+
+                # We use bulk prefetching for faster transport of the manifests.
+                # Prefetch requires an intent which it sends to the server. Here
+                # we just use operation=clone for all FMRIs.
+                intent = "operation=clone;"
+
+                # Find FMRIs which need to be added/removed.
+                to_add_set = src_fmris - targ_fmris
+                to_rm = targ_fmris - src_fmris
+
+                for f in to_add_set:
+                        to_add.append((f, intent))
+
+                del src_fmris
+                del targ_fmris
+                del to_add_set
+
+                # We have to do package removal first because after the sync we
+                # don't have the old catalog anymore and if we delete packages
+                # after the sync based on the current catalog we might delete
+                # files required by packages still in the repo.
+                if len(to_rm) > 0:
+                        msg(_("Packages to remove:"))
+                        for f in to_rm:
+                                msg("    %s" % f.get_fmri(anarchy=True))
+
+                        if not dry_run:
+                                msg(_("Removing packages ..."))
+                                if repo.get_pub_rstore(
+                                    src_pub.prefix).search_available:
+                                        del_search_index.add(src_pub.prefix)
+                                repo.remove_packages(to_rm, progtrack=tracker,
+                                    pub=src_pub.prefix)
+                                deleted_pkgs = True
+                                total_processed += len(to_rm)
+                                modified_pubs.add(src_pub.prefix)
+
+                if len(to_add) == 0:
+                        msg(_("No packages to add."))
+                        if deleted_pkgs:
+                                old_c_root = copy_catalog(src_cat_root,
+                                    src_pub.prefix)
+                        continue
+
+                get_bytes = 0
+                get_files = 0
+
+                # Retrieve manifests.
+                # Try prefetching manifests in bulk first for faster, parallel
+                # transport. Retryable errors during prefetch are ignored and
+                # manifests are retrieved again during the "Reading" phase.
+                src_pub.transport.prefetch_manifests(to_add, progtrack=tracker)
+
+                # Need to change the output of mfst_fetch since otherwise we
+                # would see "Download Manifests x/y" twice, once from the
+                # prefetch and once from the actual manifest analysis.
+                old_gti = tracker.mfst_fetch
+                tracker.mfst_fetch = progress.GoalTrackerItem(
+                    _("Reading Manifests"))
+                tracker.manifest_fetch_start(len(to_add))
+                for f, i in to_add:
+                        try:
+                                m = get_manifest(f, xport_cfg)
+                        except apx.InvalidPackageErrors, e:
+                                invalid_manifests.extend(e.errors)
+                                continue
+                        getb, getf, sendb, sendcb = get_sizes(m)
+                        get_bytes += getb
+                        get_files += getf
+
+                        if dry_run:
+                                tracker.manifest_fetch_progress(completion=True)
+                                continue
+
+                        # Move manifest into dest repo.
+                        targ_path = os.path.join(
+                            repo.get_pub_rstore(src_pub.prefix).root, 'pkg')
+                        dp = m.fmri.get_dir_path()
+                        dst_path = os.path.join(targ_path, dp)
+                        src_path = os.path.join(src_basedir, dp, 'manifest')
+                        dir_name = os.path.dirname(dst_path)
+                        try:
+                                misc.makedirs(dir_name)
+                                shutil.move(src_path, dst_path)
+                        except Exception, e:
+                                txt = _("Unable to copy manifest: %s") % e
+                                abort(err=txt)
+
+                        tracker.manifest_fetch_progress(completion=True)
+
+                tracker.manifest_fetch_done()
+                # Restore old GoalTrackerItem for manifest download.
+                tracker.mfst_fetch = old_gti
+
+                if not dry_run:
+                        msg(_("\nAdding packages ..."))
+                else:
+                        msg(_("\nAdding packages (dry-run) ..."))
+
+                status = []
+                status.append((_("Packages to add:"), str(len(to_add))))
+                status.append((_("Files to retrieve:"), str(get_files)))
+                status.append((_("Estimated transfer size:"), misc.bytes_to_str(
+                    get_bytes)))
+
+                rjust_status = max(len(s[0]) for s in status)
+                rjust_value = max(len(s[1]) for s in status)
+                for s in status:
+                        msg("%s %s" % (s[0].rjust(rjust_status),
+                            s[1].rjust(rjust_value)))
+
+                if dry_run:
+                        continue
+
+                tracker.download_set_goal(len(to_add), get_files, get_bytes)
+
+                # Retrieve package files.
+                for f, i in to_add:
+                        tracker.download_start_pkg(f)
+                        mfile = xport.multi_file_ni(src_pub, None,
+                            progtrack=tracker)
+                        m = get_manifest(f, xport_cfg)
+                        add_hashes_to_multi(m, mfile)
+
+                        if mfile:
+                                mfile.wait_files()
+
+                        tracker.download_end_pkg(f)
+                        total_processed += 1
+
+                tracker.download_done
+                tracker.reset()
+
+                modified_pubs.add(src_pub.prefix)
+                old_c_root = copy_catalog(src_cat_root, src_pub.prefix)
+
+        if invalid_manifests:
+                error(_("The following packages could not be retrieved:\n%s") %
+                    "\n".join(str(im) for im in invalid_manifests))
+
+        ret = 0
+        # Run pkgrepo verify to check repo.
+        if total_processed:
+                msg(_("\n\nVerifying repository contents."))
+                cmd = os.path.join(os.path.dirname(misc.api_cmdpath()),
+                    "pkgrepo")
+                args = [cmd, 'verify', '-s',
+                    target.get_pathname()]
+
+                try:
+                        ret = subprocess.call(args)
+                except OSError, e:
+                        raise RuntimeError, "cannot execute %s: %s" % (args, e)
+
+        # Cleanup. If verification was ok, remove backup copy of old catalog.
+        # If not, move old catalog back into place and remove messed up catalog.
+        for pub in modified_pubs:
+                c_root = repo.get_pub_rstore(pub).catalog_root
+                try:
+                        if ret:
+                                shutil.rmtree(c_root)
+                                shutil.move(old_c_root, c_root)
+                        else:
+                                shutil.rmtree(old_c_root)
+                except Exception, e:
+                        error(_("Unable to remove catalog files: %s") % e)
+                        # We don't abort here to make sure we can
+                        # restore/delete as much as we can.
+                        continue
+
+        if ret:
+                txt = _("Pkgrepo verify found errors in the updated repository."
+                    "\nThe original package catalog has been restored.\n")
+                if deleted_pkgs:
+                        txt += _("Deleted packages can not be restored.\n")
+                txt += _("The clone operation can be retried; package content "
+                    "that has already been retrieved will not be downloaded "
+                    "again.")
+                abort(err=txt)
+
+        if del_search_index:
+                txt = _("\nThe search index for the following publishers has "
+                    "been removed due to package removals.\n")
+                for p in del_search_index:
+                        txt += "    %s\n" % p
+                txt += _("\nTo restore the search index for all publishers run"
+                    "\n'pkgrepo refresh --no-catalog -s %s'.\n") % \
+                    target.get_pathname()
+                msg(txt)
+
+        cleanup()
+        if invalid_manifests and total_processed:
+                return pkgdefs.EXIT_PARTIAL
+        if invalid_manifests:
+                return pkgdefs.EXIT_OOPS
+        return pkgdefs.EXIT_OK
+
 def transfer_pkgs(pargs, target, list_newest, all_versions, all_timestamps,
-    keep_compressed, raw, recursive, dry_run, dest_xport_cfg, src_uri):
+    keep_compressed, raw, recursive, dry_run, dest_xport_cfg, src_uri, dkey,
+    dcert):
         """Retrieve source package data and optionally republish it as each
         package is retrieved.
         """
@@ -714,7 +1116,8 @@
 
                         # Setup target for transport.
                         targ_pub = transport.setup_publisher(target,
-                            src_pub.prefix, dest_xport, dest_xport_cfg)
+                            src_pub.prefix, dest_xport, dest_xport_cfg,
+                            ssl_key=dkey, ssl_cert=dcert)
 
                         # Files have to be decompressed for republishing.
                         keep_compressed = False
@@ -747,7 +1150,8 @@
                                         os.makedirs(basedir, misc.PKG_DIR_MODE)
                                 except Exception, e:
                                         error(_("Unable to create basedir "
-                                            "'%s': %s") % (basedir, e))
+                                            "'%(dir)s': %(err)s") %
+                                            {"dir": basedir, "err": e})
                                         abort()
 
                 xport_cfg.pkg_root = basedir
@@ -853,7 +1257,8 @@
                         if not targ_pub:
                                 targ_pub = transport.setup_publisher(target,
                                     src_pub.prefix, dest_xport, dest_xport_cfg,
-                                    remote_prefix=True)
+                                    remote_prefix=True, ssl_key=dkey,
+                                    ssl_cert=dcert)
 
                         try:
                                 t = trans.Transaction(target, pkg_name=pkg_name,
@@ -989,7 +1394,8 @@
                 else:
                         txt += _("No storage space left.")
 
-                tdirs = [temp_root]
+                temp_root_path = misc.get_temp_root_path()
+                tdirs = [temp_root_path]
                 if cache_dir not in tmpdirs:
                         # Only include in message if user specified.
                         tdirs.append(cache_dir)
@@ -1000,7 +1406,12 @@
                 error(txt + _("Please verify that the filesystem containing "
                    "the following directories has enough space available:\n"
                    "%s") % "\n".join(tdirs))
-                __ret = 1
+                try:
+                        cleanup()
+                except:
+                        __ret = 99
+                else:
+                        __ret = 1
         except:
                 traceback.print_exc()
                 error(misc.get_traceback_message())
--- a/src/setup.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/setup.py	Wed Aug 14 11:12:35 2013 +0530
@@ -37,6 +37,7 @@
 import py_compile
 import hashlib
 import time
+import StringIO
 
 from distutils.errors import DistutilsError, DistutilsFileError
 from distutils.core import setup
@@ -104,6 +105,7 @@
 scripts_dir = 'usr/bin'
 lib_dir = 'usr/lib'
 svc_method_dir = 'lib/svc/method'
+svc_share_dir = 'lib/svc/share'
 
 man1_dir = 'usr/share/man/man1'
 man1m_dir = 'usr/share/man/man1m'
@@ -120,9 +122,14 @@
 smf_app_dir = 'lib/svc/manifest/application/pkg'
 execattrd_dir = 'etc/security/exec_attr.d'
 authattrd_dir = 'etc/security/auth_attr.d'
+userattrd_dir = 'etc/user_attr.d'
 sysrepo_dir = 'etc/pkg/sysrepo'
 sysrepo_logs_dir = 'var/log/pkg/sysrepo'
 sysrepo_cache_dir = 'var/cache/pkg/sysrepo'
+depot_dir = 'etc/pkg/depot'
+depot_conf_dir = 'etc/pkg/depot/conf.d'
+depot_logs_dir = 'var/log/pkg/depot'
+depot_cache_dir = 'var/cache/pkg/depot'
 autostart_dir = 'etc/xdg/autostart'
 desktop_dir = 'usr/share/applications'
 gconf_dir = 'etc/gconf/schemas'
@@ -133,6 +140,8 @@
 um_share_dir = 'usr/share/update-manager'
 pm_share_dir = 'usr/share/package-manager'
 locale_dir = 'usr/share/locale'
+mirror_logs_dir = 'var/log/pkg/mirror'
+mirror_cache_dir = 'var/cache/pkg/mirror'
 
 
 # A list of source, destination tuples of modules which should be hardlinked
@@ -149,6 +158,7 @@
                 ['util/publish/pkglint.py', 'pkglint'],
                 ['util/publish/pkgmerge.py', 'pkgmerge'],
                 ['util/publish/pkgmogrify.py', 'pkgmogrify'],
+                ['util/publish/pkgsurf.py', 'pkgsurf'],
                 ['publish.py', 'pkgsend'],
                 ['pull.py', 'pkgrecv'],
                 ['sign.py', 'pkgsign'],
@@ -161,6 +171,7 @@
                 ['updatemanagernotifier.py', 'updatemanagernotifier'],
                 ['launch.py', 'pm-launch'],
                 ['sysrepo.py', 'pkg.sysrepo'],
+                ['depot-config.py', "pkg.depot-config"]
                 ],
         um_lib_dir: [
                 ['um/update-refresh.sh', 'update-refresh.sh'],
@@ -168,8 +179,15 @@
         svc_method_dir: [
                 ['svc/svc-pkg-depot', 'svc-pkg-depot'],
                 ['svc/svc-pkg-mdns', 'svc-pkg-mdns'],
+                ['svc/svc-pkg-mirror', 'svc-pkg-mirror'],
+                ['svc/svc-pkg-repositories-setup',
+                    'svc-pkg-repositories-setup'],
+                ['svc/svc-pkg-server', 'svc-pkg-server'],
                 ['svc/svc-pkg-sysrepo', 'svc-pkg-sysrepo'],
-                ['um/pkg-update', 'pkg-update'],
+                ['svc/svc-pkg-update', 'svc-pkg-update'],
+                ],
+        svc_share_dir: [
+                ['svc/pkg5_include.sh', 'pkg5_include.sh'],
                 ],
         }
 
@@ -229,12 +247,14 @@
         'man/pkgmogrify.1',
         'man/pkgsend.1',
         'man/pkgsign.1',
+        'man/pkgsurf.1',
         'man/pkgrecv.1',
         'man/pkgrepo.1',
         'man/pm-updatemanager.1',
         ]
 man1m_files = [
         'man/pkg.depotd.1m',
+        'man/pkg.depot-config.1m',
         'man/pkg.sysrepo.1m'
         ]
 man5_files = [
@@ -339,10 +359,13 @@
                     ]))
 
 smf_app_files = [
+        'svc/pkg-depot.xml',
         'svc/pkg-mdns.xml',
+        'svc/pkg-mirror.xml',
+        'svc/pkg-repositories-setup.xml',
         'svc/pkg-server.xml',
+        'svc/pkg-system-repository.xml',
         'svc/pkg-update.xml',
-        'svc/pkg-system-repository.xml',
         'svc/zoneproxy-client.xml',
         'svc/zoneproxyd.xml'
         ]
@@ -364,12 +387,27 @@
 sysrepo_log_stubs = [
         'util/apache2/sysrepo/logs/access_log',
         'util/apache2/sysrepo/logs/error_log',
+        'util/apache2/sysrepo/logs/rewrite.log',
         ]
+depot_files = [
+        'util/apache2/depot/depot.conf.mako',
+        'util/apache2/depot/depot_httpd.conf.mako',
+        'util/apache2/depot/depot_index.py',
+        ]
+depot_log_stubs = [
+        'util/apache2/depot/logs/access_log',
+        'util/apache2/depot/logs/error_log',
+        'util/apache2/depot/logs/rewrite.log',
+        ]
+# The apache-based depot includes an shtml file we add to the resource dir
+web_files.append((os.path.join(resource_dir, "web"),
+    ["util/apache2/depot/repos.shtml"]))
 execattrd_files = [
         'util/misc/exec_attr.d/package:pkg',
         'util/misc/exec_attr.d/package:pkg:package-manager'
 ]
 authattrd_files = ['util/misc/auth_attr.d/package:pkg']
+userattrd_files = ['util/misc/user_attr.d/package:pkg']
 autostart_files = [
         'um/data/updatemanagernotifier.desktop',
 ]
@@ -775,7 +813,7 @@
                         rm_f(dst)
                         os.symlink(src, dst)
 
-def run_cmd(args, swdir, updenv=None, ignerr=False):
+def run_cmd(args, swdir, updenv=None, ignerr=False, savestderr=None):
                 if updenv:
                         # use temp environment modified with the given dict
                         env = os.environ.copy()
@@ -786,6 +824,8 @@
                 if ignerr:
                         # send stderr to devnull
                         stderr = open(os.devnull)
+                elif savestderr:
+                        stderr = savestderr
                 else:
                         # just use stderr of this (parent) process
                         stderr = None
@@ -922,6 +962,50 @@
         print " ".join(args)
         run_cmd(args, os.getcwd(), updenv={"LC_ALL": "C"})
 
+def i18n_check():
+        """Checks for common i18n messaging bugs in the source."""
+
+        src_files = []
+        # A list of the i18n errors we check for in the code
+        common_i18n_errors = [
+            # This checks that messages with multiple parameters are always
+            # written using "%(name)s" format, rather than just "%s"
+            "format string with unnamed arguments cannot be properly localized"
+        ]
+
+        for line in open("po/POTFILES.in", "r").readlines():
+                if line.startswith("["):
+                        continue
+                if line.startswith("#"):
+                        continue
+                src_files.append(line.rstrip())
+
+        args = [
+            "/usr/gnu/bin/xgettext", "--from-code=UTF-8", "-o", "/dev/null"]
+        args += src_files
+
+        xgettext_output_path = tempfile.mkstemp()[1]
+        xgettext_output = open(xgettext_output_path, "w")
+        run_cmd(args, os.getcwd(), updenv={"LC_ALL": "C"},
+            savestderr=xgettext_output)
+
+        found_errs = False
+        i18n_errs = open("po/i18n_errs.txt", "w")
+        for line in open(xgettext_output_path, "r").readlines():
+                for err in common_i18n_errors:
+                        if err in line:
+                                i18n_errs.write(line)
+                                found_errs = True
+        i18n_errs.close()
+        if found_errs:
+                print >> sys.stderr, \
+"The following i18n errors were detected and should be corrected:\n" \
+"(this list is saved in po/i18n_errs.txt)\n"
+                for line in open("po/i18n_errs.txt", "r"):
+                        print >> sys.stderr, line.rstrip()
+                sys.exit(1)
+        os.remove(xgettext_output_path)
+
 def msgfmt(src, dst):
         if not dep_util.newer(src, dst):
                 return
@@ -1272,6 +1356,7 @@
         def run(self):
                 # Anything that gets created here should get deleted in
                 # clean_func.run() below.
+                i18n_check()
                 for f in intl_files:
                         intltool_merge(f, f[:-3])
 
@@ -1337,6 +1422,7 @@
                 rm_f("gui/help/C/pkg_help.pot")
 
                 rm_f("gui/help/package-manager-__LOCALE__.omf")
+                rm_f("po/i18n_errs.txt")
 
 class clobber_func(Command):
         user_options = []
@@ -1519,9 +1605,14 @@
                 (smf_app_dir, smf_app_files),
                 (execattrd_dir, execattrd_files),
                 (authattrd_dir, authattrd_files),
+                (userattrd_dir, userattrd_files),
                 (sysrepo_dir, sysrepo_files),
                 (sysrepo_logs_dir, sysrepo_log_stubs),
                 (sysrepo_cache_dir, {}),
+                (depot_dir, depot_files),
+                (depot_conf_dir, {}),
+                (depot_logs_dir, depot_log_stubs),
+                (depot_cache_dir, {}),
                 (autostart_dir, autostart_files),
                 (desktop_dir, desktop_files),
                 (gconf_dir, gconf_files),
@@ -1530,6 +1621,8 @@
                     ['gui/data/gnome-mime-application-vnd.pkg5.info.png']),
                 ('usr/share/mime/packages', ['gui/data/packagemanager-info.xml']),
                 (pm_share_dir, ['gui/data/packagemanager.ui']),
+                (mirror_cache_dir, {}),
+                (mirror_logs_dir, {}),
                 ]
         data_files += [
             (os.path.join(startpage_dir, locale), files)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/pkg-depot.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,186 @@
+<?xml version="1.0"?>
+<!--
+	CDDL HEADER START
+
+	The contents of this file are subject to the terms of the
+	Common Development and Distribution License (the "License").
+	You may not use this file except in compliance with the License.
+
+	You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+	or http://www.opensolaris.org/os/licensing.
+	See the License for the specific language governing permissions
+	and limitations under the License.
+
+	When distributing Covered Code, include this CDDL HEADER in each
+	file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+	If applicable, add the following below this CDDL HEADER, with the
+	fields enclosed by brackets "[]" replaced with your own identifying
+	information: Portions Copyright [yyyy] [name of copyright owner]
+
+	CDDL HEADER END
+
+	Copyright (c) 2013, Oracle and/or its affiliates.  All rights reserved.
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+-->
+
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<service_bundle type='manifest' name='pkg:depot'>
+
+<service
+	name='application/pkg/depot'
+	type='service'
+	version='1.0'>
+
+	<instance name='default' enabled='false'>
+		<!--
+		  Wait for network interfaces to be initialized.
+		-->
+		<dependency name='network'
+		    grouping='require_all'
+		    restart_on='error'
+		    type='service'>
+		    <service_fmri value='svc:/milestone/network:default'/>
+		</dependency>
+
+		<!--
+		  Wait for all local filesystems to be mounted.
+		-->
+		<dependency name='filesystem-local'
+		    grouping='require_all'
+		    restart_on='none'
+		    type='service'>
+		    <service_fmri
+			value='svc:/system/filesystem/local:default'/>
+		</dependency>
+
+		<!--
+		  We must wait for pkg/server instances to come online,
+		  since any readonly, non-standalone instances
+		  contribute to the configuration of pkg/depot.
+		-->
+		<dependency name='pkg-server'
+		    grouping='require_all'
+		    restart_on='none'
+		    type='service'>
+		    <service_fmri
+			value='svc:/application/pkg/server'/>
+		</dependency>
+
+		<!--
+		  Wait for automounting to be available, as we may be
+		  serving data from home directories or other remote
+		  filesystems.
+		-->
+		<dependency name='autofs'
+		    grouping='optional_all'
+		    restart_on='error'
+		    type='service'>
+		    <service_fmri
+			value='svc:/system/filesystem/autofs:default'/>
+		</dependency>
+
+		<!-- The following methods use the 'all' privilege when
+		     run, but drop privileges once they are no longer
+		     needed using ppriv -s. We need 'all' privileges to
+		     write to /system/volatile. -->
+		<exec_method
+			type='method'
+			name='start'
+			exec='/lib/svc/method/svc-pkg-depot start'
+			timeout_seconds='60'>
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv' privileges='all' />
+			</method_context>
+		</exec_method>
+
+		<!-- basic,net_privaddr are suffient for 'stop' -->
+		<exec_method
+			type='method'
+			name='stop'
+			exec='/lib/svc/method/svc-pkg-depot stop'
+			timeout_seconds='60'>
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv'
+				privileges='basic,net_privaddr' />
+			</method_context>
+		</exec_method>
+
+		<exec_method
+			type='method'
+			name='refresh'
+			exec='/lib/svc/method/svc-pkg-depot refresh'
+			timeout_seconds='60'>
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv' privileges='all' />
+			</method_context>
+		</exec_method>
+
+                <property_group name='config' type='application'>
+                        <stability value='Evolving' />
+                        <!-- The port we listen on -->
+                        <propval name='port' type='count' value='80' />
+                        <!-- The value used by Apache ServerName -->
+                        <propval name='host' type='astring' value='0.0.0.0' />
+                        <!-- Where we store apache logs -->
+                        <propval name='log_dir' type='astring'
+                                value='/var/log/pkg/depot' />
+                        <!-- Where we store runtime versions of our
+			 configuration -->
+                        <propval name='runtime_dir' type='astring'
+                                value='/system/volatile/pkg/depot' />
+                        <!-- Where we store our Mako templates for generating
+			 runtime configuration -->
+                        <propval name='template_dir' type='astring'
+                                value='/etc/pkg/depot' />
+                        <!-- Where we store our cache -->
+                        <propval name='cache_dir' type='astring'
+                                value='/var/cache/pkg/depot' />
+                        <!-- Our maximum cache size, expressed in MB -->
+                        <propval name='cache_max' type='count' value='0' />
+
+                        <!-- Whether we allow index rebuilds via admin/0
+                        Note that only "pkgrepo refresh" operations are
+                        supported, "pkgrepo rebuild" operations are not. -->
+                        <propval name='allow_refresh' type='boolean' value='false' />
+
+                        <propval name='value_authorization' type='astring'
+                                value='solaris.smf.value.pkg-depot' />
+
+
+                </property_group>
+
+		<property_group name='general' type='framework'>
+			<propval name='action_authorization'
+                            type='astring'
+                            value='solaris.smf.manage.pkg-depot' />
+			<propval name='value_authorization'
+                            type='astring'
+                            value='solaris.smf.value.pkg-depot' />
+		</property_group>
+
+		<template>
+			<common_name>
+			    <loctext xml:lang='C'>
+                                IPS Depot
+                            </loctext>
+			</common_name>
+			<documentation>
+				<manpage title='pkg.depot-config' section='1M' />
+			</documentation>
+		</template>
+
+	</instance>
+
+	<stability value='Evolving' />
+
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/pkg-mirror.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<!--
+	CDDL HEADER START
+
+	The contents of this file are subject to the terms of the
+	Common Development and Distribution License (the "License").
+	You may not use this file except in compliance with the License.
+
+	You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+	or http://www.opensolaris.org/os/licensing.
+	See the License for the specific language governing permissions
+	and limitations under the License.
+
+	When distributing Covered Code, include this CDDL HEADER in each
+	file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+	If applicable, add the following below this CDDL HEADER, with the
+	fields enclosed by brackets "[]" replaced with your own identifying
+	information: Portions Copyright [yyyy] [name of copyright owner]
+
+	CDDL HEADER END
+
+	Copyright (c) 2013, Oracle and/or its affiliates.  All rights reserved.
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+-->
+
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<service_bundle type='manifest' name='pkg:mirror'>
+
+<service
+	name='application/pkg/mirror'
+	type='service'
+	version='1'>
+
+        <!--
+          Wait for network interfaces to be initialized.
+        -->
+        <dependency name='network'
+            grouping='require_all'
+            restart_on='error'
+            type='service'>
+            <service_fmri value='svc:/milestone/network:default'/>
+        </dependency>
+
+        <!--
+          Wait for all local filesystems to be mounted.
+        -->
+        <dependency name='filesystem-local'
+            grouping='require_all'
+            restart_on='none'
+            type='service'>
+            <service_fmri
+                value='svc:/system/filesystem/local:default'/>
+        </dependency>
+
+        <!--
+          Wait for automounting to be available, as we may be
+          using data from home directories or other remote
+          filesystems.
+        -->
+        <dependency name='autofs'
+            grouping='optional_all'
+            restart_on='error'
+            type='service'>
+            <service_fmri
+                value='svc:/system/filesystem/autofs:default'/>
+        </dependency>
+
+	<!--
+	  Wait until the service which creates the
+	  <rpool>/VARSHARE/pkg/repositories container dataset to come
+	  online.
+	-->
+	<dependency name='varshare-repositories'
+	    grouping='require_all'
+	    restart_on='none'
+	    type='service'>
+	    <service_fmri
+		value='svc:/application/pkg/repositories-setup'/>
+	</dependency>
+
+        <exec_method
+                type='method'
+                name='start'
+                exec='/lib/svc/method/svc-pkg-mirror start'
+                timeout_seconds='60'>
+		<method_context>
+			<method_credential
+				user='pkg5srv' group='pkg5srv' />
+		</method_context>
+	</exec_method>
+
+        <exec_method
+                type='method'
+                name='stop'
+                exec='/lib/svc/method/svc-pkg-mirror stop'
+                timeout_seconds='60'>
+		<method_context>
+			<method_credential
+				user='pkg5srv' group='pkg5srv' />
+		</method_context>
+	</exec_method>
+
+	<!-- Since the refresh method is what causes the service to
+	perform the pkgrecv, we need an infinite timeout, as we do not
+	know how long the mirroring operation will take. -->
+	<exec_method
+                type='method'
+                name='refresh'
+                exec='/lib/svc/method/svc-pkg-mirror refresh'
+                timeout_seconds='0'>
+		<method_context>
+			<method_credential
+				user='pkg5srv' group='pkg5srv' />
+		</method_context>
+	</exec_method>
+
+
+	<property_group name='general' type='framework'>
+        	<propval name='action_authorization' type='astring'
+        	        value='solaris.smf.manage.pkg-mirror' />
+		<propval
+                	name='value_authorization'
+	                type='astring'
+        	        value='solaris.smf.value.pkg-mirror' />
+        </property_group>
+
+	<property_group name='startd' type='framework'>
+		<propval name='duration' type='astring'
+			value='transient' />
+	</property_group>
+
+        <property_group name='config' type='application'>
+                <stability value='Evolving' />
+
+		<!-- The local repository we pkgrecv to. By default,
+		if we the parent directory is at the top-level of a
+		zfs dataset, we attempt to create a new dataset for the
+		repository. For this to happen, 'pkg5srv' must have
+		appropriate zfs delegations on that dataset, eg.
+
+		# zfs allow pkg5srv create,mount,snapshot <dataset>
+
+		In the default configuration, a dataset is created by
+		svc:/application/pkg/varshare-repositories which we
+		have a dependency on.
+		-->
+                <propval name='repository' type='astring'
+			value='/var/share/pkg/repositories/solaris' />
+
+                <!-- A partial crontab(1) entry defining how often we
+		update the repository. We allow the special value
+		'random' in the 3rd (day of the month) field in order
+		to even the load on busy repository servers. This gets
+		replaced when the service is first started with a random
+		day in the range 1-28. -->
+                <propval name='crontab_period' type='astring'
+			value='30 2 random * *' />
+
+		<!-- The reference image we use to pull publisher,
+		origin, proxy and ssl key/cert information from -->
+		<propval name='ref_image' type='astring'
+			value='/' />
+
+		<!-- The publishers configured in the image at
+		'config/ref_image' which we receive from.
+		 -->
+		<propval name='publishers' type='astring'
+			value='solaris' />
+
+		<!-- The cache_dir used for the -c option to pkgrecv(1M)
+		-->
+                <propval name='cache_dir' type='astring'
+                        value='/var/cache/pkg/mirror' />
+
+		<!-- Enable additional debugging of the service. -->
+                <propval name='debug' type='boolean' value='false' />
+
+		<propval
+                	name='value_authorization'
+	                type='astring'
+        	        value='solaris.smf.manage.pkg-mirror' />
+        </property_group>
+
+        <!-- To work around an SMF bug, we create a default instance
+	containing the 'config' property group, specifiying the
+	authorizations we need to allow clients to modify values in it.
+	User-created instances should create this pg with the same
+	'value_authorization' property. -->
+        <instance name="default" complete="true" enabled="false">
+                <property_group name='config' type='application'>
+                <stability value='Evolving' />
+                <propval name='repository' type='astring'
+			value='/var/share/pkg/repositories/solaris' />
+                <propval name='crontab_period' type='astring'
+			value='30 2 random * *' />
+                <propval name='ref_image' type='astring' value='/' />
+		<propval name='publishers' type='astring'
+			value='solaris' />
+                <propval name='cache_dir' type='astring'
+                        value='/var/cache/pkg/mirror' />
+                <propval name='debug' type='boolean' value='false' />
+
+		<propval
+                	name='value_authorization'
+	                type='astring'
+        	        value='solaris.smf.manage.pkg-mirror' />
+                </property_group>
+        </instance>
+	<stability value='Evolving' />
+
+        <template>
+                <common_name>
+                    <loctext xml:lang='C'>IPS Repository Mirror</loctext>
+                </common_name>
+                <documentation>
+                        <manpage title='pkgrecv' section='1M' />
+                </documentation>
+        </template>
+
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/pkg-repositories-setup.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+	CDDL HEADER START
+
+	The contents of this file are subject to the terms of the
+	Common Development and Distribution License (the "License").
+	You may not use this file except in compliance with the License.
+
+	You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+	or http://www.opensolaris.org/os/licensing.
+	See the License for the specific language governing permissions
+	and limitations under the License.
+
+	When distributing Covered Code, include this CDDL HEADER in each
+	file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+	If applicable, add the following below this CDDL HEADER, with the
+	fields enclosed by brackets "[]" replaced with your own identifying
+	information: Portions Copyright [yyyy] [name of copyright owner]
+
+	CDDL HEADER END
+
+	Copyright (c) 2013, Oracle and/or its affiliates.  All rights reserved.
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+-->
+
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<service_bundle type='manifest' name='pkg:repositories-setup'>
+
+<service
+	name='application/pkg/repositories-setup'
+	type='service'
+	version='1'>
+
+	<!-- This SMF service creates a dataset
+	 <rpool>/VARSHARE/pkg/repositories and assigns zfs delegations
+	to allow 'pkg5srv' to create,mount and snapshot datasets within
+	<rpool>/VARSHARE/pkg
+	-->
+
+	<create_default_instance enabled='true' />
+
+        <!--
+          Wait for all local filesystems to be mounted.
+        -->
+        <dependency name='filesystem-local'
+            grouping='require_all'
+            restart_on='none'
+            type='service'>
+            <service_fmri
+                value='svc:/system/filesystem/local:default'/>
+        </dependency>
+
+        <exec_method
+                type='method'
+                name='start'
+                exec='/lib/svc/method/svc-pkg-repositories-setup start'
+                timeout_seconds='60'>
+	</exec_method>
+
+        <exec_method
+                type='method'
+                name='stop'
+                exec=':true'
+                timeout_seconds='60'>		
+	</exec_method>
+
+	<property_group name='startd' type='framework'>
+		<propval name='duration' type='astring'
+			value='transient' />
+	</property_group>
+
+        
+	<stability value='Evolving' />
+
+        <template>
+                <common_name>
+                    <loctext xml:lang='C'>IPS rpool/VARSHARE/pkg creation</loctext>
+                </common_name>
+        </template>
+
+</service>
+
+</service_bundle>
--- a/src/svc/pkg-server.xml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/pkg-server.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 
 	CDDL HEADER END
 
-	Copyright (c) 2009, 2011 Oracle and/or its affiliates.  All rights reserved.
+	Copyright (c) 2009, 2013 Oracle and/or its affiliates.  All rights reserved.
 
 	NOTE:  This service manifest is not editable; its contents will
 	be overwritten by package or patch operations, including
@@ -34,7 +34,7 @@
 <service
 	name='application/pkg/server'
 	type='service'
-	version='1'>
+	version='1.1'>
 
 	<create_default_instance enabled='false' />
 
@@ -82,13 +82,13 @@
 	<exec_method
 		type='method'
 		name='start'
-		exec='%{pkg/pkg_root}/lib/svc/method/svc-pkg-depot %m'
+		exec='%{pkg/pkg_root}/lib/svc/method/svc-pkg-server %m'
 		timeout_seconds='0' />
 
 	<exec_method
 		type='method'
 		name='stop'
-		exec='%{pkg/pkg_root}/lib/svc/method/svc-pkg-depot %m %{restarter/contract}'
+		exec='%{pkg/pkg_root}/lib/svc/method/svc-pkg-server %m %{restarter/contract}'
 		timeout_seconds='30' />
 
 	<property_group name='pkg' type='application'>
@@ -116,6 +116,7 @@
 		<propval name='sort_file_max_size' type='astring' value=''/>
 		<propval name='file_root' type='astring' value='' />
 		<property name='address' type='net_address'/>
+                <propval name='standalone' type='boolean' value='true'/>
 	</property_group>
 
 	<property_group name='pkg_bui' type='application'>
--- a/src/svc/pkg-system-repository.xml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/pkg-system-repository.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 
 	CDDL HEADER END
 
-	Copyright (c) 2011, Oracle and/or its affiliates.  All rights reserved.
+	Copyright (c) 2011, 2013 Oracle and/or its affiliates.  All rights reserved.
 
 	NOTE:  This service manifest is not editable; its contents will
 	be overwritten by package or patch operations, including
@@ -71,23 +71,47 @@
 			value='svc:/system/filesystem/autofs:default'/>
 		</dependency>
 
+		<!-- The following methods use the 'all' privilege when
+		     run, but drop privileges once they are no longer
+		     needed using ppriv -s. We need 'all' privileges to
+		     write to /system/volatile. -->
 		<exec_method
 			type='method'
 			name='start'
 			exec='/lib/svc/method/svc-pkg-sysrepo start'
-			timeout_seconds='60' />
+			timeout_seconds='60'>
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv' privileges='all' />
+			</method_context>
+		</exec_method>
 
+
+		<!-- basic,net_privaddr are suffient for 'stop' -->
 		<exec_method
 			type='method'
 			name='stop'
 			exec='/lib/svc/method/svc-pkg-sysrepo stop'
-			timeout_seconds='60' />
+			timeout_seconds='60' >
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv'
+				privileges='basic,net_privaddr' />
+			</method_context>
+		</exec_method>
+
 
 		<exec_method
 			type='method'
 			name='refresh'
 			exec='/lib/svc/method/svc-pkg-sysrepo refresh'
-			timeout_seconds='60' />
+			timeout_seconds='60' >
+			<method_context>
+             			<method_credential user='pkg5srv'
+				group='pkg5srv' privileges='all' />
+		        </method_context>
+		</exec_method>
+
 
                 <property_group name='config' type='application'>
                         <stability value='Evolving' />
@@ -101,7 +125,7 @@
                         <!-- Where we store runtime versions of our
 			 configuration -->
                         <propval name='runtime_dir' type='astring'
-                                value='/system/volatile/pkg/sysrepo' />
+				value='/system/volatile/pkg/sysrepo' />
                         <!-- Where we store our Mako templates for generating
 			 runtime configuration -->
                         <propval name='template_dir' type='astring'
--- a/src/svc/pkg-update.xml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/pkg-update.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 
 	CDDL HEADER END
 
-	Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+	Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 	NOTE:  This service manifest is not editable; its contents will
 	be overwritten by package or patch operations, including
@@ -63,21 +63,25 @@
 	<exec_method
 		type='method'
 		name='start'
-		exec='lib/svc/method/pkg-update start'
+		exec='lib/svc/method/svc-pkg-update start'
 		timeout_seconds='60' />
 
 	<exec_method
 		type='method'
 		name='stop'
-		exec='lib/svc/method/pkg-update stop'
+		exec='lib/svc/method/svc-pkg-update stop'
 		timeout_seconds='60' />
 
 	<property_group name='startd' type='framework'>
 		<propval name='duration' type='astring' value='transient' />
 	</property_group>
 
+	<!--
+        Create a property group to allow the update service to
+        record the time it last ran.
+        See /usr/lib/update-manager/update-refresh.sh
+	-->
 	<property_group name='update' type='application'>
-		<propval name='image_dir' type='astring' value='/' />
 	</property_group>
 
 	<stability value='Unstable' />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/pkg5_include.sh	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,205 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2008, 2013 Oracle and/or its affiliates.  All rights reserved.
+#
+
+CP=/usr/bin/cp
+CRONTAB=/usr/bin/crontab
+DIFF=/usr/bin/diff
+GREP=/usr/bin/grep
+ID=/usr/bin/id
+MKDIR=/usr/bin/mkdir
+RM=/usr/bin/rm
+RMDIR=/usr/bin/rmdir
+SLEEP=/usr/bin/sleep
+SVCADM=/usr/sbin/svcadm
+SVCPROP=/usr/bin/svcprop
+
+#
+# Check whether the supplied exit code is 0, printing an error message
+# if it is not, optionally either disabling an FMRI or exiting.
+#
+# Usage:
+# check_failure \
+#     <int exit status>  <error message> <fmri> <mode>
+#
+function check_failure {
+
+	typeset RESULT=$1
+	typeset ERR_MSG=$2
+	typeset FMRI=$3
+	typeset MODE=$4
+
+	if [ $RESULT -ne 0 ] ; then
+		echo "Error: $ERR_MSG"
+		if [ "$MODE" = "degrade" ] ; then
+			echo "Moving service $FMRI to maintenance mode."
+			$SVCADM mark maintenance $FMRI
+		elif [ "$MODE" = "exit" ] ; then
+			exit 1
+		fi
+	fi
+	return $RESULT
+}
+
+#
+# Attempt to acquire a pkg5-private lock on the current users crontab.
+# Note that this only protects crontab from multiple callers using
+# this function, this isn't a generic locking mechanism for cron.
+#
+function acquire_crontab_lock {
+	LOCK_OWNED="false"
+	UID=$($ID -u)
+	while [ "$LOCK_OWNED" == "false" ]; do
+		$MKDIR /tmp/pkg5-crontab-lock.$UID > /dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			LOCK_OWNED=true
+		else
+			$SLEEP 0.1
+		fi
+	done
+}
+
+function release_crontab_lock {
+	UID=$($ID -u)
+	$RMDIR /tmp/pkg5-crontab-lock.${UID}
+}
+
+#
+# Update cron with a new crontab file.  We pass what we expect the
+# current crontab looks like in order to verify that the content hasn't
+# changed since we made our modifications.  Note that between the time
+# we check for crontab modifications, and the time we apply the new
+# crontab entries, another program could have altered the crontab entry,
+# this is unfortunate, but unlikely.
+#
+# Usage:
+#  update_crontab <current crontab> <new crontab>
+#
+function update_crontab {
+
+	typeset CURRENT_CRONTAB=$1
+	typeset NEW_CRONTAB=$2
+	EXIT=0
+	CRONTAB_LOCKDIR=/tmp/pkg5-crontab-lock.$UID
+
+	$CRONTAB -l > $CRONTAB_LOCKDIR/actual-crontab.$$
+	$DIFF $CRONTAB_LOCKDIR/actual-crontab.$$ - \
+	    < $CURRENT_CRONTAB 2>&1 \
+	    >  /dev/null
+	if [ $? == 0 ]; then
+		$CRONTAB $NEW_CRONTAB
+		EXIT=$?
+	else
+		echo "Crontab file was modified unexpectedly!"
+		EXIT=1
+	fi
+	$RM $CRONTAB_LOCKDIR/actual-crontab.$$
+	return $EXIT
+}
+
+#
+# Add a cron job to the current users crontab entry, passing the FMRI
+# we're doing work for, the cron schedule (the first 5 fields of the
+# crontab entry) and the command we'd like to run.
+# We perform primitive locking around cron to protect this function from
+# multiple processes.
+#
+# This function assumes only a single occurrence of a given command is
+# valid in a crontab entry: multiple instances of the same command with
+# the same arguments, but with different schedules are not allowed.
+#
+# Usage:
+# add_cronjob <fmri> <schedule> <cmd>
+#
+function add_cronjob {
+
+	typeset FMRI=$1
+	typeset SCHEDULE=$2
+	typeset CMD=$3
+
+	UID=$($ID -u)
+	CRONTAB_LOCKDIR=/tmp/pkg5-crontab-lock.$UID
+
+	typeset new_crontab=$CRONTAB_LOCKDIR/pkg5-new-crontab.$$
+	typeset current_crontab=$CRONTAB_LOCKDIR/pkg5-current-crontab.$$
+
+	#
+	# adding a cron job is essentially just looking for an existing
+	# entry, removing it, and appending a new one.
+	#
+	acquire_crontab_lock
+	$CRONTAB -l > $current_crontab
+	EXIT=0
+	# if the crontab doesn't already contain our command, add it
+	$GREP -q "^[0-9, \*]+ $CMD"$ $current_crontab
+	if [ $? -ne 0 ]; then
+		$GREP -v " ${CMD}"$ $current_crontab > $new_crontab
+		echo "$SCHEDULE $CMD" >> $new_crontab
+
+		update_crontab $current_crontab $new_crontab
+		EXIT=$?
+		$RM $new_crontab
+	fi
+	$RM $current_crontab
+	release_crontab_lock
+
+	return $EXIT
+}
+
+#
+# Remove a cron job from the current users crontab entry. We pass the
+# FMRI we're doing work for, and the command we wish to remove from
+# the crontab. If the the command does not exist in the crontab, this
+# is treated as an error. Note that all instances of a given command
+# are removed.
+#
+# Usage:
+# remove_cronjob <fmri> <cmd>
+#
+function remove_cronjob {
+
+	typeset fmri=$1
+	typeset cmd=$2
+
+	UID=$($ID -u)
+	CRONTAB_LOCKDIR=/tmp/pkg5-crontab-lock.$UID
+	new_crontab=$CRONTAB_LOCKDIR/pkg5-new-crontab.$$
+	current_crontab=$CRONTAB_LOCKDIR/pkg5-current-crontab.$$
+
+	acquire_crontab_lock
+	$CRONTAB -l > $current_crontab
+	$GREP "${cmd}" $current_crontab > /dev/null 2>&1
+	check_failure $? "command $cmd did not exist in crontab" $fmri \
+	    degrade
+
+	$GREP -v "${cmd}" $current_crontab > $new_crontab
+
+	update_crontab $current_crontab $new_crontab
+	EXIT=$?
+
+	$RM $current_crontab $new_crontab
+	release_crontab_lock
+
+	return $EXIT
+}
--- a/src/svc/svc-pkg-depot	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/svc-pkg-depot	Wed Aug 14 11:12:35 2013 +0530
@@ -19,129 +19,246 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2009, 2010 Oracle and/or its affiliates.  All rights reserved.
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
-# Load SMF constants and functions
 . /lib/svc/share/smf_include.sh
 
-if [[ -z "$SMF_FMRI" ]]; then
-	echo "this script can only be invoked by smf(5)"
-	exit $SMF_EXIT_ERR_NOSMF
-fi
+APACHE_HOME=/usr/apache2/2.2
+APACHE_ETC_ROOT=/etc/pkg/depot
+APACHE_BIN=${APACHE_HOME}/bin/64
 
-case "$1" in
-'start')
-	# Handles depot startup
+#
+# Calling $APACHE_BIN/apachectl would source $APACHE_BIN/envvars, which
+# in turn would source /etc/apache2/2.2/envvars, if it exists.
+#
+# We want to keep the depot service completely separate from
+# the site system configuration used by svc:/network/http:apache22
+# avoiding /etc/apache2, which means we must avoid apachectl.
+#
+# In this method script, we call httpd directly instead, but as a
+# result, we also need to include the relevant contents of
+# $APACHE_BIN/envvars - setting $LD_LIBRARY_PATH as it does.
+#
+HTTPD=${APACHE_BIN}/httpd.worker
+LD_LIBRARY_PATH=${APACHE_HOME}/lib/64:${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+
+function check_prop {
+	if [ -z "$1" ]; then
+		echo "ERROR: SMF property for $2 was empty"
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+}
+
+function get_pair {
+        NAME=$1
+        shift 2
+        echo "${NAME}=\"$@\""
+        echo "export ${NAME}"
+}
 
-	# retrieve the pkg_root property. If the variable is left empty
-	# pkg_root is /
-	pkg_root=$(svcprop -p pkg/pkg_root $SMF_FMRI)
-	if [[ $? -ne 0 ]]; then
-		echo "service property pkg/pkg_root not defined for" \
-		    "service: $SMF_FMRI"
-		exit $SMF_EXIT_ERR_CONFIG
-	fi
+# A function to pull in the config properties from the FMRI given
+# as the first argument. This allows us to make a single call
+# to svcprop, rather than calling svcprop for each value we
+# want to retrieve.
+function get_smf_props {
+
+	IFS="
+"
+	SMF_PROPS="$(svcprop -t -p config $1 |\
+        	sed -e 's#config/#depot_#g' -e 's/$/,/g')"
+	IFS=,
+	for line in $SMF_PROPS ; do
+        	IFS=' 
+'
+        	eval $(get_pair $line)
+	done
+}
+
 
-	# make sure pkg_root ends with a /
-	echo $pkg_root | grep /$ >/dev/null
-	if [[ $? -ne 0 ]]; then
-		pkg_root="${pkg_root}/"
+function check_failure {
+	RESULT=$1
+	MESSAGE=$2
+	NON_FATAL=$3
+	if [ $RESULT -ne 0 ]; then
+		echo $MESSAGE
+		if [ -n "$NON_FATAL" ]; then
+			return
+		fi
+		exit $SMF_EXIT_ERR_FATAL
 	fi
+}
 
-	# adjust the PYTHONPATH to point to the current environment
-	# we need to make sure to adjust the PYTHONPATH accordingly
-	# to a Python 2.4 or 2.6 environment
-	python_ver=$(head -1 ${pkg_root}usr/lib/pkg.depotd 2>/dev/null |
-	    awk -F/ '{print $NF}')
-	if [[ $python_ver != *python* ]]; then
-		echo "invalid python version $python_ver found in"
-		echo "${pkg_root}usr/lib/pkg.depotd"
+function check_apache_failure {
+	RESULT=$1
+	MESSAGE=$2
+	if [ $RESULT -ne 0 ]; then
+		echo $MESSAGE
+		kill_apache
 		exit $SMF_EXIT_ERR_FATAL
 	fi
-
-	PYTHONPATH=${pkg_root}usr/lib/${python_ver}/vendor-packages/:$PYTHONPATH
-
-	export PYTHONPATH
+}
 
-	#
-	# If this process has net_privaddr, then we pass it along.
-	# If not, we ensure that we don't specify it, since that will
-	# cause ppriv to throw an error.
-	#
-	privaddr=""
-	ppriv -v $$ | grep 'E: ' | grep net_privaddr > /dev/null 2>&1
-	if [[ $? == 0 ]]; then
-		echo "Dropping net_privaddr privilege."
-		privaddr=",net_privaddr"
-	fi
+function abspath {
+	# print a normalized version of a path, needed because
+	# many utilities will not dereference non-existent directories
+	# in path names, e.g. cat /etc/no-such-dir/../motd will fail.
+	echo $1 | /usr/bin/python -c \
+    'import os.path ; import sys ; print os.path.normpath(sys.stdin.read())'
+}
+
+function run_depot {
 
-	#
-	# Build up the privileges available starting with "basic".  This
-	# provides some protection even when the depot runs as root.
-	#
-	wrapper="ppriv -s \
-            A=basic,-file_link_any,-proc_info,-proc_session$privaddr -e"
+        /usr/lib/pkg.depot-config \
+               -S \
+               -c ${depot_cache_dir} \
+               -h ${depot_host} \
+               -l ${depot_log_dir} \
+               -p ${depot_port} \
+               -r ${depot_runtime_dir} \
+               -s ${depot_cache_max} \
+               -T ${depot_template_dir} \
+               -t apache2 \
+               ${depot_allow_refresh}
+	failure=$?
+	if [ $? -ne 0 ] ; then
+		# make sure we leave nothing behind
+		kill_apache
+		kill_htcacheclean
+	        check_failure $failure \
+	            "pkg.depot-config: failed to create Apache config"
+	fi
+}
 
-	# Build the command to start pkg.depotd.
-	cmd="$wrapper ${pkg_root}usr/lib/pkg.depotd --cfg $SMF_FMRI"
+function run_htcacheclean {
+	# if we dropped to maintenance and are in the process of
+	# clearing that state,  we may have htcacheclean processes
+	# hanging around.
+	kill_htcacheclean
+	if [ "${depot_cache_max}" != "0" ] ; then
+		# Start a cache cleaning daemon, scanning every 2 weeks,
+		# being intelligent about only running if the cache has
+		# changed, limiting the cache to ${depot_cache_max}
+		# megabytes, being nice about scheduling and removing
+		# empty directories if necessary.
+	       interval=$((60 * 24 * 14))
+               /usr/apache2/2.2/bin/htcacheclean \
+                       -d${interval} -i -l ${depot_cache_max}M -n \
+                       -p ${depot_cache_dir} \
+                       -P ${depot_cache_dir}/../depot_htcacheclean.pid \
+                       -t
+               check_failure $? "htcacheclean failed to run cleanly"
+       fi
+}
 
-	# Echo the command so that the log contains the command used to start
-	# the depot.
-	echo $cmd
-
-	exec $cmd
-
-	;;
+function kill_htcacheclean {
+	pid_file=$(abspath ${depot_cache_dir}/../depot_htcacheclean.pid)
+	if [ -f $pid_file ]; then
+                PID=$(< $pid_file)
+                /usr/bin/kill -TERM $PID
+                check_failure $? "failed to kill htcacheclean process\
+ $PID" "not_fatal"
+        fi
+}
 
-'stop')
-	#
-	# Strategy: First, try shutting down depot using polite kill.  Use up
-	# as much as possible of the allotted timeout period waiting for polite
-	# kill to take effect.  As time runs out, try a more aggressive kill.
-	#
-	SVC_TIMEOUT=`svcprop -p stop/timeout_seconds $SMF_FMRI`
-	if [[ $? -ne 0 ]]; then
-		echo "service property stop/timeout_seconds not defined" \
-		    "for service: $SMF_FMRI"
-		exit $SMF_EXIT_ERR_CONFIG
+function kill_apache {
+	# We go to lengths to kill remaining httpd processes: if we kill
+	# just the pid, then child httpd.worker processes become
+	# zombies, hanging onto the server port, which causes problems
+	# when trying to start a service that is transitioning from
+	# maintenance.
+	# This function should only be called when the service is
+	# transitioning to maintenance: normal Apache shutdown is
+	# preferable.
+	pid_file=$(abspath ${depot_runtime_dir}/../depot_httpd.pid)
+	if [ -f $pid_file ]; then
+		PID=$(< $pid_file)
+		/usr/bin/ptree $PID | /usr/bin/awk '{print $1}' | \
+		    /usr/bin/xargs /usr/bin/kill -TERM
+		check_failure $? "failed to kill apache process $PID" \
+		    "not_fatal"
+		/usr/bin/rm $pid_file
 	fi
+}
+
+function server_ping {
+	# Ping the service, ensuring the index gets built if does
+	# not exist.
+	# Since curl --retry uses an exponential backoff algorithm, this
+	# can result in us waiting 40 seconds, which ought to be long
+	# enough for Apache to come online. (index refreshes are run in
+	# the background on the server after it has returned a response)
+	url="http://${depot_host}:${depot_port}"
+	ipv6=$(echo ${depot_host} | /usr/bin/grep :)
+	if [ -n "$ipv6" ] ; then
+		url="http://\[${depot_host}\]:${depot_port}"
+	fi
+	/usr/bin/curl -s --max-time 5 --retry 4 -o /dev/null ${url} \
+2> /dev/null
+	check_failure $? "Unable to access the server at ${url}. Check\
+ the SMF service log or the error log at ${depot_log_dir}/error_log for\
+ more information, if any."
+}
 
-	#
-	# Note that we're working around an oddity in smf_kill_contract: it
-	# waits in 5 second chunks and can overshoot the specified timeout
-	# by as many as 4 seconds.  Example: a specified wait of 6 will result
-	# in a wait of 10 seconds in reality.  Since we may potentially do a
-	# first kill and then a second, we must ensure that at least 8 seconds
-	# of slop is left in reserve.  To be paranoid, we go for 10.
-	#
-	((POLITE=$SVC_TIMEOUT - 10))
-	if [[ $POLITE -gt 0 ]]; then
-		smf_kill_contract $2 TERM 1 $POLITE
-		ret=$?
-		# '2' indicates timeout with non-empty contract.
-		if [[ $ret -eq 2 ]]; then
-			echo "Gentle contract kill timed out after" \
-			    "$POLITE seconds, trying SIGKILL." >&2
-			#
-			# Again, despite the specified timeout, this will
-			# take a minimum of 5 seconds to complete.
-			#
-			smf_kill_contract $2 KILL 1 1
-			if [[ $ret -ne 0 ]]; then
-				exit $SMF_EXIT_ERR_FATAL
-			fi
-		fi
-	else
-		# If the timeout is too short, we just try once, politely.
-		smf_kill_contract $2 TERM
-	fi
+get_smf_props $SMF_FMRI
+check_prop ${depot_host} config/host
+check_prop ${depot_port} config/port
+check_prop ${depot_log_dir} config/log_dir
+check_prop ${deport_template_dir} config/template_dir
+check_prop ${depot_runtime_dir} config/runtime_dir
+check_prop ${depot_cache_dir} config/cache_dir
+check_prop ${depot_cache_max} config/cache_max
+check_prop ${depot_allow_refresh} config/allow_refresh
+if [ "${depot_allow_refresh}" == "true" ] ; then
+	depot_allow_refresh="-A"
+else
+	depot_allow_refresh=""
+fi
+
+FAILED_TO_RUN="Server failed to %s. Check the SMF service log or the\
+ error log at ${depot_log_dir}/error_log for more information, if any."
+
+case "$1" in
+"start")
+	cmd="start"
+	run_depot
+	# drop privileges now that we've written our configuration
+	/usr/bin/ppriv -s E=basic,net_privaddr $$
+	run_htcacheclean
+        emsg=$(/usr/bin/printf ${FAILED_TO_RUN} start)
+	${HTTPD} -f ${depot_runtime_dir}/depot_httpd.conf \
+            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+ 	check_apache_failure $? $emsg
+        server_ping
 	;;
-
+"refresh")
+	cmd="graceful"
+	run_depot
+	# drop privileges now that we've written our configuration
+	/usr/bin/ppriv -s E=basic,net_privaddr $$
+	kill_htcacheclean
+	run_htcacheclean
+        emsg=$(/usr/bin/printf ${FAILED_TO_RUN} refresh)
+	${HTTPD} -f ${depot_runtime_dir}/depot_httpd.conf \
+            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+	check_apache_failure $? $emsg
+        server_ping
+	;;
+"stop")
+	cmd="stop"
+	kill_htcacheclean
+        emsg=$(/usr/bin/printf ${FAILED_TO_RUN} stop)
+	${HTTPD} -f ${depot_runtime_dir}/depot_httpd.conf \
+            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+	check_apache_failure $? $emsg
+	;;
 *)
-	echo "Usage: $0 { start | stop }"
+	echo "Usage: $0 {start|stop|refresh}"
 	exit $SMF_EXIT_ERR_CONFIG
 	;;
+esac
 
-esac
 exit $SMF_EXIT_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/svc-pkg-mirror	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,511 @@
+#!/usr/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013 Oracle and/or its affiliates.  All rights reserved.
+#
+
+#
+# This is the method script for the svc:/application/pkg/mirror service
+#
+# When called using the 'start' or 'stop'  SMF method script, it adds
+# or removes a crontab entry for the user running the service, pkg5srv
+# by default.
+#
+
+#
+# When called using the 'refresh' method, it runs pkgrecv(1) to update a
+# pkg(5) repository using configuration stored in the SMF instance.
+#
+# The following SMF properties are used to configure the service:
+#
+# config/repository		the local pkg5 repository we update.
+#
+# config/ref_image		the reference pkg5 image that contains
+#				origin information that we should update
+#				from.
+#
+# config/publishers		a comma-separated list of the publishers
+#				from ref_image that we pkgrecv from.
+#
+# config/crontab_period		the first five fields of a crontab(4)
+#				entry, with the 3rd field allowing the
+#				special value 'random'.
+#
+# config/debug			a boolean, 'true' or 'false'; whether
+#				to log more output when debugging.
+#
+
+# Load SMF constants and functions
+. /lib/svc/share/smf_include.sh
+. /lib/svc/share/fs_include.sh
+. /lib/svc/share/pkg5_include.sh
+
+AWK=/usr/bin/awk
+CAT=/usr/bin/cat
+DATE=/usr/bin/date
+GREP=/usr/bin/grep
+PKG=/usr/bin/pkg
+PKGRECV=/usr/bin/pkgrecv
+PKGREPO=/usr/bin/pkgrepo
+PYTHON=/usr/bin/python
+RM=/usr/bin/rm
+SED=/usr/bin/sed
+SORT=/usr/bin/sort
+SVCCFG=/usr/sbin/svccfg
+SVCPROP=/usr/bin/svcprop
+WC=/usr/bin/wc
+ZFS=/usr/sbin/zfs
+
+SVCNAME=svc:/application/pkg/mirror
+
+#
+# Since we deal with '*' values in crontab fields, we never want
+# globbing.
+#
+set -o noglob
+
+#
+# Multiple instances of this service should not point at the
+# same local repository, since they could step on each other's toes
+# during updates, so we check for this before enabling the service.
+#
+# Usage:
+#    check_duplicate_repos
+#
+function check_duplicate_repos {
+
+	ALL_REPOS=$($SVCPROP -p config/repository "$SVCNAME:*" \
+	    | $AWK '{print $NF}' | $SORT | $WC -l)
+	REPOS=$($SVCPROP -p config/repository "$SVCNAME:*" \
+	    | $AWK '{print $NF}' | $SORT -u | $WC -l)
+	#
+	# if the unique list of repositories is not the same as the
+	# list of repositories, then we have duplicates.
+	#
+	if [ "$ALL_REPOS" != "$REPOS" ]; then		
+		return 1
+	fi
+	return 0
+}
+
+#
+# In order that all instances don't hit the remote origins on the same
+# day, when configured with a 'config/crontab_period' containing a
+# special value 'random' in the 'day of the month' field of the crontab
+# schedule, we randomize the day, choosing a value from 1-28, storing
+# that to the service config instead. We then print the crontab period.
+#
+# Usage:
+#    add_date_jitter
+#
+function add_date_jitter {
+
+	schedule=$($SVCPROP -p config/crontab_period $SMF_FMRI \
+	    | $SED -e 's/\\//g')
+
+	#
+	# Validate the cron_period property value, checking that we have
+	# exactly 5 fields, and that 'random' only appears in the 3rd
+	# field.  We leave other validation up to cron(1).
+	#
+	echo "$schedule" | $AWK '
+		NF != 5 {
+			print "config/crontab_period property must contain 5 " \
+			    "values.";
+			exit 1
+		}
+		$1 == "random" || $2 == "random" || $4 == "random" || \
+		    $5 == "random" {
+			print "only field 3 can have the value random";
+			exit 1
+		}'
+
+	check_failure $? "invalid value for config/crontab_period." \
+	    $SMF_FMRI exit
+
+	RAND=$(( ($RANDOM % 27) + 1 ))
+	new_schedule=$(echo "$schedule" | $SED -e "s/random/$RAND/1")
+	if [ "$new_schedule" != "$schedule" ]; then
+		#
+		# Save the schedule in the instance. Note that this
+		# will not appear in the running instance until the
+		# refresh method has fired.
+		#
+		new_schedule=$(echo $new_schedule| $SED -e 's/ /\\ /g')
+		$SVCCFG -s $SMF_FMRI setprop \
+		    config/crontab_period = astring: \"$new_schedule\"
+	fi
+	print $new_schedule
+}
+
+#
+# Add a crontab entry that does periodic pkgrecvs from a series of
+# remote pkg5 origins to a local repository. This is run as part of the
+# SMF start method for this service. If the repository doesn't exist,
+# we create it.  We also attempt to create a zfs dataset if the parent
+# directory for the repository is the leaf of a zfs dataset.
+#
+function smf_schedule_updates {
+
+	check_duplicate_repos
+	check_failure $? "Two or more instances of $SVCNAME contain the
+same 'config/repository' value, which is not supported." $SMF_FMRI exit
+	typeset -f schedule=$(add_date_jitter | $SED -e 's/\\//g')
+	typeset repo=$($SVCPROP -p config/repository $SMF_FMRI)
+
+	SAVED_IFS="$IFS"
+	IFS=,
+	set -A publishers $($SVCPROP -p config/publishers $SMF_FMRI)
+	IFS="$SAVED_IFS"
+
+	if [ ! -f $repo/pkg5.repository ]; then
+		repo_parent=$(dirname $repo)
+		repo_base=$(basename $repo)
+		readmnttab "$repo_parent" < /etc/mnttab
+		if [ "$fstype" = "zfs" ]; then
+			#
+			# $special gets set by readmnttab in
+			# /lib/svc/share/fs_include.sh
+			#
+			DS="$special/$repo_base"
+			$ZFS create $DS
+			check_failure $? \
+			    "unable to create zfs dataset $DS" \
+			    $SMF_FMRI degrade
+		fi
+		$PKGREPO create "$repo"
+		check_failure $? "unable to create repository" \
+		    $SMF_FMRI degrade
+	fi
+	set_default_publisher "$repo" ${publishers[0]}
+	add_cronjob $SMF_FMRI "$schedule" \
+	    "/usr/sbin/svcadm refresh $SMF_FMRI"
+}
+
+#
+# Remove the crontab entry that was added by 'schedule_updates'. This is
+# run as part of the SMF stop method for this service.
+#
+function smf_unschedule_updates {
+
+	remove_cronjob $SMF_FMRI \
+	    "/usr/sbin/svcadm refresh $SMF_FMRI"
+}
+
+#
+# Checks whether the given repository has a publisher/prefix set,
+# and if not, sets it to the given publisher.
+#
+# Usage:
+#     set_default_publisher <path to repo> <publisher>
+#
+function set_default_publisher {
+	typeset repo="$1"
+	typeset pub=$2
+
+	DEFAULT=$($PKGREPO -s "$repo" get -H publisher/prefix | \
+	    $AWK '{print $NF}')
+	if [ "$DEFAULT" = '""' ]; then
+		$PKGREPO -s "$repo" set publisher/prefix=$pub
+	fi
+}
+
+#
+# Intended to be called as part of a cron job firing, this calls
+# 'pkgrecv_from_origin' for each publisher configured in the SMF
+# instance.
+#
+# Usage: 
+#     update_repository <smf fmri>
+#
+function update_repository {
+
+	typeset SMF_FMRI=$1
+	typeset instance=$(echo $SMF_FMRI | $AWK -F: '{print $NF}')
+	typeset lockfile=/var/log/pkg/mirror/mirror.$instance.lock
+
+	if [ -f $lockfile ]; then
+		pid=$(<$lockfile)
+		check_failure 1 "A mirror operation was already running
+ under process $pid when the cron job fired. Remove $lockfile to
+ override, or check the SMF property 'config/crontab_period' to ensure
+ cron schedules don't overlap." $SMF_FMRI degrade
+		return 1
+	fi
+	# write our pid into the lock file
+	echo $$ > $lockfile
+	check_failure $? "unable to create lockfile" $SMF_FMRI degrade
+
+	typeset repo=$($SVCPROP -p config/repository $SMF_FMRI \
+	    | $SED -e 's/\\//g')
+	typeset cachedir=$($SVCPROP -p config/cache_dir $SMF_FMRI \
+	    | $SED -e 's/\\//g')
+	typeset ref_image=$($SVCPROP -p config/ref_image $SMF_FMRI\
+	    | $SED -e 's/\\//g')
+
+	SAVED_IFS="$IFS"
+	IFS=,
+	set -A publishers $($SVCPROP -p config/publishers $SMF_FMRI)
+	IFS="$SAVED_IFS"
+	if [ -z "$publishers" ]; then
+		echo "ERROR: no publishers found in 'config/publishers'"
+		return $SMF_EXIT_FATAL
+	fi
+
+	set -A origins ""
+	set -A ssl_keys ""
+	set -A ssl_certs ""
+	set -A http_proxies ""
+	set -A https_proxies ""
+
+	#
+	# Gather the details we need to connect to the origins
+	# we want to pkgrecv from.
+	#
+	i=0
+	while [ $i -lt ${#publishers[@]} ]; do
+		pub=${publishers[$i]}
+		sslkey=$($PKG -R $ref_image publisher $pub \
+		    | $GREP 'SSL Key:' \
+		    | $GREP -v None | $SED -e 's/.* //g')
+		sslcert=$($PKG -R $ref_image publisher $pub \
+		    | $GREP 'SSL Cert:' \
+		    | $GREP -v None | $SED -e 's/.* //g')
+		$PKG -R $ref_image publisher -F tsv > /tmp/pkg.mirror.$$
+
+		index=0
+		#
+		# this function depends on the output of
+		# 'pkg publisher -F tsv'. It really ought to use
+		# 'pkg publisher -o' option when that's available.
+		#
+		while read publisher sticky syspub enabled ptype status \
+		    uri proxy ; do
+			if [ "$pub" != "$publisher" ]; then
+				continue
+			fi
+			if [ -z "$uri" ]; then
+				echo "WARNING: no URI \
+configured for publisher $pub"
+				continue
+			fi
+			origins[$index]=$uri
+			echo $uri | $GREP -q https://
+			if [ $? -eq 0 ]; then
+				ssl_keys[$index]=$sslkey
+				ssl_certs[$index]=$sslcert
+			else
+				ssl_keys[$index]=''
+				ssl_certs[$index]=''
+			fi
+			if [ "$proxy" = "-" ]; then
+				proxy=''
+			fi
+			https_proxies[$index]=$proxy
+			http_proxy[$index]=$proxy
+			index=$(( $index + 1 ))
+		done < /tmp/pkg.mirror.$$
+		$RM /tmp/pkg.mirror.$$
+		i=$(( $i + 1 ))
+	done
+
+	# Iterate over all configured origins
+	i=0
+	while [ $i -lt ${#origins[@]} ]; do
+		origin=${origins[$i]}
+		key=${ssl_keys[$i]}
+		cert=${ssl_certs[$i]}
+		http_proxy=${http_proxies[$i]}
+		https_proxy=${https_proxies[$i]}
+
+		pkgrecv_from_origin "$repo" "$origin" "$key" \
+		    "$cert" $SMF_FMRI "$cachedir" "$http_proxy" \
+		    "$https_proxy"
+		check_failure $? \
+		    "unable to update repository $repo" $SMF_FMRI \
+		    degrade
+		if [ $? -ne 0 ]; then
+			$RM $lockfile
+			return 1
+		fi
+		i=$(( $i + 1 ))
+	done
+
+	EXIT=$?
+	$RM $lockfile
+	return $EXIT
+}
+
+#
+# When retrieving values from SMF, we can get the string '""'
+# (two quotes) returned.  For our purposes, this is equivalent to the
+# null string, so we normalize it to ''. This function reads from stdin.
+#
+function reduce_null_str {
+	while read value; do
+		if [ "$value" = '""' ]; then
+			echo ''
+		else
+			echo $value
+		fi
+	done
+}
+
+#
+# Perform a pkgrecv from the given origin to the given repository.
+# We assume that the repository exists.
+#
+# Usage:
+#    pkgrecv_from_origin <repo> <origin> <key path> <cert path> <FMRI>
+#			<cache dir> <http_proxy> <https_proxy>
+#
+function pkgrecv_from_origin {
+
+	typeset repo=$1
+	typeset origin=$2
+	typeset key=$(echo $3 | reduce_null_str)
+	typeset cert=$(echo $4 | reduce_null_str)
+	typeset SMF_FMRI=$5
+	typeset cachedir=$6
+	typeset http_proxy=$(echo $7 | reduce_null_str)
+	typeset https_proxy=$(echo $8 | reduce_null_str)
+
+	typeset instance=$(echo $SMF_FMRI | $AWK -F: '{print $NF}')
+	typeset debug_flag=$($SVCPROP -p config/debug $SMF_FMRI)
+	typeset LOG=/var/log/pkg/mirror/mirror.$instance.log
+
+	export http_proxy=$http_proxy
+	export https_proxy=$https_proxy
+
+	TSTAMP=$($DATE +%Y%m%dT%H%M%SZ)
+	echo "$TSTAMP: $SMF_FMRI updates to $repo from $origin :" \
+	    >> $LOG
+
+	if [ -n "$key" ] && [ -n "$cert" ]; then
+		key="--key $key"
+		cert="--cert $cert"
+	fi
+	# show the command we're running
+	if [ "$debug_flag" = "true" ] ; then
+		echo $PKGRECV -s $origin -c "$cachedir"/$instance \
+		    -d "$repo" -m all-timestamps $key $cert '*'
+	fi
+	$PKGRECV -s $origin -c "$cachedir"/$instance -d "$repo" \
+	    -m all-timestamps $key $cert '*' >  $LOG.tmp 2>&1
+	EXIT=$?
+
+	if [ "$debug_flag" = "true" ]; then
+		$CAT $LOG.tmp >> $LOG
+	elif [ $EXIT -ne 0 ]; then
+		#
+		# in the case of errors, getting the full pkgrecv output
+		# can be helpful.
+		#
+		$CAT $LOG.tmp >> $LOG
+	else
+		# otherwise, we only log messages containing pkg5 FMRIs
+		$GREP 'pkg:/' $LOG.tmp >> $LOG
+		# we only destroy the cache if a pkgrecv was successful
+		$RM -rf "$cachedir"/$instance
+	fi
+	$PKGREPO -s "$repo" refresh
+	$RM $LOG.tmp
+	return $EXIT
+}
+
+# $1 start | stop | an FMRI containing configuration
+case "$1" in
+'start')
+	smf_schedule_updates
+	if [ $? -eq 0 ]; then
+	    result=$SMF_EXIT_OK
+	else
+	    echo "Problem mirroring repository for $SMF_FMRI"
+	    result=$SMF_EXIT_ERR_FATAL
+	fi
+	;;
+
+'stop')
+	smf_unschedule_updates
+	if [ $? -eq 0 ]; then
+	    result=$SMF_EXIT_OK
+	else
+	    echo "Problem mirroring repository for $SMF_FMRI"
+	    result=$SMF_EXIT_ERR_FATAL
+	fi
+	;;
+
+#
+# A note on logging.
+#
+# The following log files are created while this service is running:
+#
+# /var/log/pkg/mirror/mirror.<instance>.log
+#	This is the top-level log file for the service. This log
+#	shows a summary of each pkgrecv, listing a timestamp and the
+#	packages that were received during that run of the cron job.
+#
+# /var/log/pkg/mirror/mirror.<instance>.run.<pid>
+# 	This is a temporary log file, which should contain very little
+#       output - it exists to capture all other output from the service
+#	If 'config/debug' is set, then this file will also include the
+#       full pkgrecv(1) command that is executed.
+#
+# /var/log/pkg/mirror/mirror.<instance>.log.tmp
+#       Another temporary log file, which captures the complete output
+#       of each pkgrecv command as it runs. At the end of the pkgrecv
+#       process, we extract a summary and append it to
+#	mirror.<instance>.log. If 'config/debug' is set, the contents
+#       of this log are appended to mirror.<instance>.log. If any errors
+#	were encountered while running pkgrecv, the contents of this log
+#	are appended to mirror.<instance>.log.
+#
+
+'refresh')
+	typeset instance=$(echo $SMF_FMRI | $AWK -F: '{print $NF}')
+	typeset LOG=/var/log/pkg/mirror/mirror.$instance.log
+	typeset debug_flag=$($SVCPROP -p config/debug $SMF_FMRI)
+
+	# Most output should get captured by update_repository, but we
+	# capture any remaining output.
+	update_repository $SMF_FMRI > $LOG.run.$$ 2>&1
+	RET=$?
+
+	if [ -s $LOG.run.$$ ]; then
+		cat $LOG.run.$$ >> $LOG
+	fi
+
+	if [ "$debug_flag" = "false" ]; then
+		$RM $LOG.run.$$
+	fi
+
+	if [ $RET -eq 0 ]; then
+		result=$SMF_EXIT_OK
+	else
+		echo "Mirror refresh failed: see $LOG for more detail."
+		# try to remove the cron job so we don't keep failing
+		smf_unschedule_updates
+		result=$SMF_EXIT_ERR_FATAL
+	fi
+	;;
+esac
+
+exit $result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/svc-pkg-repositories-setup	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,72 @@
+#!/usr/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013 Oracle and/or its affiliates.  All rights reserved.
+#
+
+# Load SMF constants and functions
+. /lib/svc/share/smf_include.sh
+. /lib/svc/share/fs_include.sh
+. /lib/svc/share/pkg5_include.sh
+
+CHOWN=/usr/bin/chown
+ZFS=/usr/sbin/zfs
+
+result=$SMF_EXIT_ERR_FATAL
+
+case "$1" in
+'start')
+	# check if we already have a mounted /var/share/pkg/repositories
+	readmnttab /var/share/pkg/repositories < /etc/mnttab
+	if [ "$fstype" = zfs ] ; then
+		exit $SMF_EXIT_OK
+	else
+		rootistmpmnt=0
+		readmnttab / < /etc/mnttab
+		if [ "$fstype" = zfs ] ; then
+			#
+			# $special gets set by readmnttab in
+			# /lib/svc/share/fs_include.sh
+			#
+			be=$special
+			rpool=$(print $be | cut -d / -f1)			
+		else
+			# we're on a LiveCD, so exit immediately.
+			exit $SMF_EXIT_OK
+		fi
+		DS="$rpool/VARSHARE/pkg/repositories"
+		$ZFS create -p $DS
+		check_failure $? "Unable to create $DS" $SMF_FMRI exit
+
+		$ZFS allow pkg5srv create,mount,snapshot "$DS"
+		check_failure $? \
+		    "Unable to delegate ZFS permissions on $DS" \
+		    $SMF_FMRI exit
+
+		$CHOWN pkg5srv:pkg5srv /var/share/pkg/repositories
+		check_failure $? \
+		    "Unable to chown /var/share/pkg/repositories" \
+		    $SMF_FMRI exit
+	fi
+	;;
+esac
+
+exit $SMF_EXIT_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/svc-pkg-server	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,178 @@
+#!/usr/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2009, 2013 Oracle and/or its affiliates.  All rights reserved.
+#
+
+# Load SMF constants and functions
+. /lib/svc/share/smf_include.sh
+
+if [[ -z "$SMF_FMRI" ]]; then
+	echo "this script can only be invoked by smf(5)"
+	exit $SMF_EXIT_ERR_NOSMF
+fi
+
+case "$1" in
+'start')
+	# Handles server startup
+
+	# retrieve the pkg_root property. If the variable is left empty
+	# pkg_root is /
+	pkg_root=$(svcprop -p pkg/pkg_root $SMF_FMRI)
+	if [[ $? -ne 0 ]]; then
+		echo "service property pkg/pkg_root not defined for" \
+		    "service: $SMF_FMRI"
+		exit $SMF_EXIT_ERR_CONFIG
+	fi
+
+	# make sure pkg_root ends with a /
+	echo $pkg_root | grep /$ >/dev/null
+	if [[ $? -ne 0 ]]; then
+		pkg_root="${pkg_root}/"
+	fi
+
+        # if configured readonly & standalone, refresh the depot service,
+        # if is is present, and exit immediately as a transient service.
+        readonly=$(svcprop -p pkg/readonly $SMF_FMRI)
+        standalone=$(svcprop -p pkg/standalone $SMF_FMRI)
+        if [[ "$readonly" == "true" ]] && [[ "$standalone" == "false" ]] && \
+           [[ -f /usr/lib/pkg.depot-config ]]; then
+                svcadm refresh svc:/application/pkg/depot
+                svcadm enable svc:/application/pkg/depot
+                smf_method_exit $SMF_EXIT_TEMP_TRANSIENT \
+                    "managed_by_depot" \
+                    "svc:/application/pkg/depot configuration updated."
+        fi
+
+	# adjust the PYTHONPATH to point to the current environment
+	# we need to make sure to adjust the PYTHONPATH accordingly
+	# to a Python 2.4 or 2.6 environment
+	python_ver=$(head -1 ${pkg_root}usr/lib/pkg.depotd 2>/dev/null |
+	    awk -F/ '{print $NF}')
+	if [[ $python_ver != *python* ]]; then
+		echo "invalid python version $python_ver found in"
+		echo "${pkg_root}usr/lib/pkg.depotd"
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+
+	PYTHONPATH=${pkg_root}usr/lib/${python_ver}/vendor-packages/:$PYTHONPATH
+
+	export PYTHONPATH
+
+	#
+	# If this process has net_privaddr, then we pass it along.
+	# If not, we ensure that we don't specify it, since that will
+	# cause ppriv to throw an error.
+	#
+	privaddr=""
+	ppriv -v $$ | grep 'E: ' | grep net_privaddr > /dev/null 2>&1
+	if [[ $? == 0 ]]; then
+		echo "Dropping net_privaddr privilege."
+		privaddr=",net_privaddr"
+	fi
+
+	#
+	# Build up the privileges available starting with "basic".  This
+	# provides some protection even when pkg.depotd runs as root.
+	#
+	wrapper="ppriv -s \
+            A=basic,-file_link_any,-proc_info,-proc_session$privaddr -e"
+
+	# Build the command to start pkg.depotd.
+	cmd="$wrapper ${pkg_root}usr/lib/pkg.depotd --cfg $SMF_FMRI"
+
+	# Echo the command so that the log contains the command used to start
+	# pkg.depotd.
+	echo $cmd
+
+	exec $cmd
+
+	;;
+
+'stop')
+
+        # if configured readonly & standalone, exit immediately as transient
+        # unless we've got a running pkg.depotd process, which happens if the
+        # user has modified the pkg/server configuration, but hasn't restarted
+        # the server in order to apply those changes.
+        readonly=$(svcprop -p pkg/readonly $SMF_FMRI)
+        standalone=$(svcprop -p pkg/standalone $SMF_FMRI)
+
+        if [[ "$readonly" == "true" ]] && [[ "$standalone" == "false" ]]  && \
+            [[ -f /usr/lib/pkg.depot-config ]] ; then
+                svcadm refresh svc:/application/pkg/depot
+                if [ -z "$2" ] ; then
+                        # there's no existing pkg.depotd - we can exit now.
+                        echo "depot in use, stop method script complete."
+                        exit $SMF_EXIT_OK
+                fi
+        fi
+
+	#
+	# Strategy: First, try shutting down pkg.depotd using polite kill.  Use up
+	# as much as possible of the allotted timeout period waiting for polite
+	# kill to take effect.  As time runs out, try a more aggressive kill.
+	#
+	SVC_TIMEOUT=`svcprop -p stop/timeout_seconds $SMF_FMRI`
+	if [[ $? -ne 0 ]]; then
+		echo "service property stop/timeout_seconds not defined" \
+		    "for service: $SMF_FMRI"
+		exit $SMF_EXIT_ERR_CONFIG
+	fi
+
+	#
+	# Note that we're working around an oddity in smf_kill_contract: it
+	# waits in 5 second chunks and can overshoot the specified timeout
+	# by as many as 4 seconds.  Example: a specified wait of 6 will result
+	# in a wait of 10 seconds in reality.  Since we may potentially do a
+	# first kill and then a second, we must ensure that at least 8 seconds
+	# of slop is left in reserve.  To be paranoid, we go for 10.
+	#
+	((POLITE=$SVC_TIMEOUT - 10))
+	if [[ $POLITE -gt 0 ]]; then
+		smf_kill_contract $2 TERM 1 $POLITE
+		ret=$?
+		# '2' indicates timeout with non-empty contract.
+		if [[ $ret -eq 2 ]]; then
+			echo "Gentle contract kill timed out after" \
+			    "$POLITE seconds, trying SIGKILL." >&2
+			#
+			# Again, despite the specified timeout, this will
+			# take a minimum of 5 seconds to complete.
+			#
+			smf_kill_contract $2 KILL 1 1
+			if [[ $ret -ne 0 ]]; then
+				exit $SMF_EXIT_ERR_FATAL
+			fi
+		fi
+	else
+		# If the timeout is too short, we just try once, politely.
+		smf_kill_contract $2 TERM
+	fi
+	;;
+
+*)
+	echo "Usage: $0 { start | stop }"
+	exit $SMF_EXIT_ERR_CONFIG
+	;;
+
+esac
+exit $SMF_EXIT_OK
--- a/src/svc/svc-pkg-sysrepo	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/svc-pkg-sysrepo	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
 #
 
 . /lib/svc/share/smf_include.sh
@@ -105,11 +105,11 @@
                # nice about scheduling and removing empty directories if
                # necessary.
 	       interval=$((60 * 24 * 14))
-               /usr/bin/su pkg5srv -c "/usr/apache2/2.2/bin/htcacheclean \
+               /usr/apache2/2.2/bin/htcacheclean \
                        -d${interval} -i -l ${SYSREPO_CACHE_MAX}M -n \
                        -p ${SYSREPO_CACHE_DIR} \
                        -P ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid \
-                       -t"
+                       -t
                check_failure $? "htcacheclean failed to run cleanly"
        fi
 }
@@ -172,6 +172,8 @@
 "start")
 	cmd="start"
 	run_sysrepo
+	# drop privileges now that we've written our configuration
+	/usr/bin/ppriv -s E=basic,net_privaddr $$
 	run_htcacheclean
 	${HTTPD} -f ${SYSREPO_RUNTIME_DIR}/sysrepo_httpd.conf \
             ${STARTUP_OPTIONS} -k ${cmd} 2>&1
@@ -180,6 +182,8 @@
 "refresh")
 	cmd="graceful"
 	run_sysrepo
+	# drop privileges now that we've written our configuration
+	/usr/bin/ppriv -s E=basic,net_privaddr $$
 	/usr/bin/pkill -USR1 -ox zoneproxyd
 	kill_htcacheclean
 	run_htcacheclean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/svc-pkg-update	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,51 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2008, 2013 Oracle and/or its affiliates.  All rights reserved.
+#
+# An SMF method script for
+# svc:/application/pkg/update:default
+# It's sole purpose is to add or remove a crontab entry
+
+. /lib/svc/share/smf_include.sh
+. /lib/svc/share/pkg5_include.sh
+
+REFRESH_PROG="/usr/lib/update-manager/update-refresh.sh"
+SCHEDULE='30 0,9,12,18,21 * * *'
+
+case $SMF_METHOD in
+"start")
+	add_cronjob $SMF_FMRI "$SCHEDULE" $REFRESH_PROG
+	check_failure $? "unable to schedule pkg refreshes" $SMF_FMRI \
+	    exit
+	;;
+"stop")
+	remove_cronjob $SMF_FMRI $REFRESH_PROG
+	check_failure $? "unable to unschedule pkg refreshes" $SMF_FMRI\
+	    exit
+	;;
+*)
+	echo "Command line invocation of ${0} unsupported."
+	echo "This script is intended for smf(5) invocation only"
+	exit $SMF_EXIT_ERR_NOSMF
+	;;
+esac
+exit $SMF_EXIT_OK
--- a/src/svc/zoneproxyd.xml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/svc/zoneproxyd.xml	Wed Aug 14 11:12:35 2013 +0530
@@ -2,7 +2,7 @@
 <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
 <!--
 
- Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
 
  CDDL HEADER START
 
@@ -72,7 +72,8 @@
 		exec='/usr/lib/zones/zoneproxyd'
 		timeout_seconds='300'>
 		<method_context>
-			<method_credential user='root'/>
+			<method_credential user='pkg5srv'
+				privileges='all' />
 		</method_context>
 	</exec_method>
 
@@ -82,7 +83,7 @@
 		exec=':kill'
 		timeout_seconds='300'>
 		<method_context>
-			<method_credential user='root'/>
+			<method_credential user='pkg5srv' />
 		</method_context>
 	</exec_method>
 
--- a/src/sysrepo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/sysrepo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -59,7 +59,7 @@
 orig_cwd = None
 
 PKG_CLIENT_NAME = "pkg.sysrepo"
-CLIENT_API_VERSION = 73
+CLIENT_API_VERSION = 75
 pkg.client.global_settings.client_name = PKG_CLIENT_NAME
 
 # exit codes
--- a/src/tests/README	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/README	Wed Aug 14 11:12:35 2013 +0530
@@ -14,14 +14,25 @@
 
   run.py can also be run standalone with a variety of options:
 
-	Usage: run.py [-ghpv] [-b filename] [-o regexp]
+	Usage: run.py [-ghptv] [-c format] [-b filename] [-o regexp]
+	       run.py [-hptvx] [-c format] [-b filename] [-s regexp] [-o regexp]
+	   -a <dir>       Archive failed test cases to <dir>/$pid/$testcasename
+	   -b <filename>  Baseline filename
+	   -c <format>    Collect code coverage data in xml or html format
+	   -d             Show debug output, including commands run, and outputs
+	   -f             Show fail/error information even when test is expected to fail
 	   -g             Generate result baseline
 	   -h             This help message
+	   -j             Parallelism
+	   -o <regexp>    Run only tests that match regexp
 	   -p             Parseable output format
+	   -q             Quiet output
+	   -s <regexp>    Run tests starting at regexp
+	   -t             Generate timing info file
+	   -u             Enable IPS GUI tests, disabled by default
 	   -v             Verbose output
-	   -b <filename>  Baseline filename
-	   -o <regexp>    Run only tests that match regexp
-	   -c             Collect code coverage data
+	   -x             Stop after the first baseline mismatch
+	   -z <port>      Lowest port the test suite should use
 
   When adding, removing, or changing the results of test cases, make
   sure to update baseline.txt and check it in.  This can be done with the
--- a/src/tests/api/t_api_list.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_api_list.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -179,7 +179,7 @@
 
         def setUp(self):
                 pkg5unittest.ManyDepotTestCase.setUp(self, ["test1", "test2",
-                    "test3"])
+                    "test3", "test1"])
 
                 pkg_data = ""
                 for p in self.packages:
@@ -238,8 +238,8 @@
 
                         pkg_data += "close\n"
 
-                rurl1 = self.dcs[1].get_repo_url()
-                plist = self.pkgsend_bulk(rurl1, pkg_data)
+                self.rurl1 = self.dcs[1].get_repo_url()
+                plist = self.pkgsend_bulk(self.rurl1, pkg_data)
 
                 # Ensure that the second repo's packages have exactly the same
                 # timestamps as those in the first ... by copying the repo over.
@@ -267,11 +267,16 @@
                 # The third repository should remain empty and not be
                 # published to.
 
+                # The fourth should be for test1, but have only the oldest
+                # version of the 'apple' package.
+                self.rurl4 = self.dcs[4].get_repo_url()
+                self.pkgrecv(self.rurl1, "-d %s %s" % (self.rurl4, plist[0]))
+
                 # Next, create the image and configure publishers.
-                self.image_create(rurl1, prefix="test1",
+                self.image_create(self.rurl1, prefix="test1",
                     variants={ "variant.mumble": "true" })
-                rurl2 = self.dcs[2].get_repo_url()
-                self.pkg("set-publisher -g " + rurl2 + " test2")
+                self.rurl2 = self.dcs[2].get_repo_url()
+                self.pkg("set-publisher -g " + self.rurl2 + " test2")
 
         def assertPrettyEqual(self, actual, expected):
                 if actual == expected:
@@ -1262,7 +1267,19 @@
                 ]
                 self.assertPrettyEqual(returned, expected)
 
+                # Verify the results for LIST_UPGRADABLE when publisher
+                # repository no longer has installed package.
+                self.pkg("unset-publisher test2")
+                self.pkg("set-publisher -G '*' -g %s test1" % self.rurl4)
+                api_obj = self.get_img_api_obj()
+
+                returned = self.__get_returned(api_obj.LIST_UPGRADABLE,
+                    api_obj=api_obj)
+                self.assertPrettyEqual(returned, [])
+
                 # Reset image state for following tests.
+                self.pkg("set-publisher -G '*' -g " + self.rurl1 + " test1")
+                self.pkg("set-publisher -p " + self.rurl2)
                 for pd in api_obj.gen_plan_uninstall(["*"]):
                         continue
                 api_obj.prepare()
--- a/src/tests/api/t_catalog.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_catalog.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -31,6 +31,7 @@
 import errno
 import os
 import shutil
+import simplejson
 import stat
 import unittest
 
@@ -388,228 +389,36 @@
                 self.assertEqual(self.npkgs, self.c.package_count)
                 self.assertEqual(self.nversions, self.c.package_version_count)
 
-        def test_02_extract_matching_fmris(self):
+        def test_02_gen_packages(self):
                 """Verify that the filtering logic provided by
-                extract_matching_fmris works as expected."""
-
-                cf = fmri.PkgFmri("pkg:/[email protected],5.10-1:20070101T120000Z")
-                cl = catalog.extract_matching_fmris(self.c.fmris(),
-                    patterns=[cf])[0]
-                self.assertEqual(len(cl), 7)
+                gen_packages works as expected."""
 
-                cf = fmri.PkgFmri("pkg:/[email protected],5.11-1:20061231T120000Z")
-                cl = catalog.extract_matching_fmris(self.c.fmris(),
-                    patterns=[cf])[0]
-                self.assertEqual(len(cl), 7)
+                f = "pkg:/[email protected],5.11-1:20000101T120000Z"
+                cl = list(self.c.gen_packages(patterns=[f]))
+                self.assertEqual(len(cl), 1)
 
-                cf = fmri.PkgFmri("pkg:/[email protected],5.11-2")
-                cl = catalog.extract_matching_fmris(self.c.fmris(),
-                    patterns=[cf])[0]
+                f = "pkg:/[email protected]"
+                cl = list(self.c.gen_packages(patterns=[f]))
                 self.assertEqual(len(cl), 5)
 
-                cf = fmri.PkgFmri("pkg:/[email protected],5.11-3")
-                cl = catalog.extract_matching_fmris(self.c.fmris(),
-                    patterns=[cf])[0]
-                self.assertEqual(len(cl), 4)
-
-                # First, verify that passing a single version pattern
-                # works as expected.
-
-                # Sorts by stem, then version, then publisher.
-                def extract_order(a, b):
-                        res = cmp(a.pkg_name, b.pkg_name)
-                        if res != 0:
-                                return res
-                        res = cmp(a.version, b.version) * -1
-                        if res != 0:
-                                return res
-                        return cmp(a.publisher, b.publisher)
+                f = "pkg:/[email protected]"
+                cl = list(self.c.gen_packages(patterns=[f], pubs=["foobar"]))
+                self.assertEqual(len(cl), 0)
 
-                # This is a dict containing the set of fmris that are expected
-                # to be returned by extract_matching_fmris keyed by version
-                # pattern.
-                versions = {
-                    "*": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "1.0": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "1.1": ["pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "*.1": ["pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "3.*": ["pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z"],
-                    "3.2.*": ["pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z"],
-                    "3.*.*": ["pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z"],
-                    "*,5.11": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "*,*-*": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "*,*-*.2": ["pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z"],
-                    "*,*-*.*.3": ["pkg:/[email protected],5.11-1.2.3:20000101T120052Z"],
-                    "*,*-1": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "*,*-1.2": ["pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z"],
-                    "*,*-1.2.*": ["pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z"],
-                    "*,*-*:*": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                }
+                # zpkg exists in contrib.opensolaris.org (2 fmris) and extra (1)
+                f = "zpkg"
+                cl = list(self.c.gen_packages(patterns=[f]))
+                self.assertEqual(len(cl), 3)
+                cl = list(self.c.gen_packages(patterns=[f], pubs=["extra"]))
+                self.assertEqual(len(cl), 1)
 
-                for pat in versions:
-                        chash = {}
-                        rlist = []
-                        for f in catalog.extract_matching_fmris(self.c.fmris(),
-                            counthash=chash, versions=[pat])[0]:
-                                f.set_publisher(None)
-                                rlist.append(f)
-
-                        # Custom sort the returned and expected to avoid having
-                        # to define test data in extract order.  The primary
-                        # interest here is in what is returned, not the order.
-                        rlist = sorted([
-                            fmri.PkgFmri(f.get_fmri(anarchy=True))
-                            for f in rlist
-                        ])
-                        rlist = [f.get_fmri() for f in rlist]
-
-                        elist = sorted([
-                            fmri.PkgFmri(e)
-                            for e in versions[pat]
-                        ])
-                        elist = [f.get_fmri() for f in elist]
-
-                        # Verify that the list of matches are the same.
-                        self.assertEqual(rlist, elist)
-
-                        # Verify that the same number of matches was returned
-                        # in the counthash.
-                        self.assertEqual(chash[pat], len(versions[pat]))
-
-                # Last, verify that providing multiple versions for a single
-                # call returns the expected results.
-
-                # This is a dict containing the set of fmris that are expected
-                # to be returned by extract_matching_fmris keyed by version
-                # pattern.
-                versions = {
-                    "*,*-1": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                    "*,*-*:*": ["pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120000Z",
-                        "pkg:/[email protected],5.11-1:20000101T120010Z",
-                        "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                        "pkg:/[email protected],5.11-2:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120050Z",
-                        "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                        "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                        "pkg:/[email protected],5.11-1:20000101T120014Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z",
-                        "pkg:/[email protected],5.11-1:20000101T120040Z"],
-                }
-
-                elist = [
-                    "pkg:/[email protected],5.11-1:20000101T120040Z",
-                    "pkg:/[email protected],5.11-1:20000101T120000Z",
-                    "pkg:/[email protected],5.11-1:20000101T120010Z",
-                    "pkg:/[email protected],5.11-1.1:20000101T120020Z",
-                    "pkg:/[email protected],5.11-1.2:20000101T120030Z",
-                    "pkg:/[email protected],5.11-2:20000101T120040Z",
-                    "pkg:/[email protected],5.11-1:20000101T120040Z",
-                    "pkg:/[email protected],5.11-1:20000101T120050Z",
-                    "pkg:/[email protected],5.11-1.2:20000101T120051Z",
-                    "pkg:/[email protected],5.11-1.2.3:20000101T120052Z",
-                    "pkg:/[email protected],5.11-1:20000101T120014Z",
-                    "pkg:/[email protected],5.11-1:20000101T120040Z",
-                    "pkg:/[email protected],5.11-1:20000101T120040Z",
-                ]
-
-                rlist = catalog.extract_matching_fmris(self.c.fmris(),
-                    counthash=chash, versions=versions.keys())[0]
-                rlist = sorted([
-                    fmri.PkgFmri(f.get_fmri(anarchy=True))
-                    for f in rlist
-                ])
-                rlist = [f.get_fmri() for f in rlist]
-
-                # Verify that the list of matches are the same.
-                self.assertEqual(rlist, elist)
-
-                for pat in versions:
-                        # Verify that the same number of matches was returned
-                        # in the counthash.
-                        self.assertEqual(chash[pat], len(versions[pat]))
+                patterns = ["pkg:/[email protected]", "willnotmatch"]
+                unmatched = set()
+                matched = set()
+                cl = list(self.c.gen_packages(patterns=patterns,
+                    matched=matched, unmatched=unmatched))
+                self.assertEqual(unmatched, set(["willnotmatch"]))
+                self.assertEqual(matched, set(["pkg:/[email protected]"]))
 
         def test_03_permissions(self):
                 """Verify that new catalogs are created with a mode of 644 and
@@ -1316,10 +1125,10 @@
                 self.assertEqual(self.c.package_count, 0)
                 self.assertEqual(self.c.package_version_count, 0)
 
-        def test_02_extract_matching_fmris(self):
-                cf = fmri.PkgFmri("pkg:/[email protected],5.10-1:20070101T120000Z")
-                cl = catalog.extract_matching_fmris(self.c.fmris(),
-                    patterns=[cf])[0]
+        def test_02_gen_packages(self):
+                cf = fmri.PkgFmri("pkg:/[email protected],5.11-1:20070101T120000Z")
+                fmris = [str(s) for s in self.c.fmris()]
+                cl = list(self.c.gen_packages(patterns=fmris))
                 self.assertEqual(len(cl), 0)
 
         def test_03_actions(self):
@@ -1330,5 +1139,114 @@
                 self.assertEqual(returned, [])
 
 
+class TestCorruptCatalog(pkg5unittest.Pkg5TestCase):
+        """Tests against various forms of corrupted catalogs."""
+
+        def test_corrupt_attrs1(self):
+                """Raise InvalidCatalogFile for a catalog.attrs w/ bogus JSON"""
+                f = open(os.path.join(self.test_root, "catalog.attrs"), "w")
+                f.write('{"valid json": "but not a catalog"}')
+                f.close()
+                self.assertRaises(api_errors.InvalidCatalogFile,
+                    catalog.Catalog, meta_root=self.test_root)
+
+        def test_corrupt_attrs2(self):
+                """Raise InvalidCatalogFile for a catalog.attrs w/ garbage"""
+                f = open(os.path.join(self.test_root, "catalog.attrs"), "w")
+                print >> f, 'garbage'
+                f.close()
+                self.assertRaises(api_errors.InvalidCatalogFile,
+                    catalog.Catalog, meta_root=self.test_root)
+
+        def test_corrupt_attrs3(self):
+                """Raise InvalidCatalogFile for a catalog.attrs missing an
+                element"""
+                # make catalog
+                c = catalog.Catalog(meta_root=self.test_root)
+                c.save()
+
+                # corrupt it
+                fname = os.path.join(self.test_root, "catalog.attrs")
+                f = open(fname, "r")
+                struct = simplejson.load(f)
+                f.close()
+                del struct["parts"]
+                f = open(fname, "w")
+                print >> f, simplejson.dumps(struct)
+                f.close()
+
+                self.assertRaises(api_errors.InvalidCatalogFile,
+                    catalog.Catalog, meta_root=self.test_root)
+
+        def test_corrupt_attrs4(self):
+                """Raise BadCatalogSignatures for a catalog.attrs with
+                corrupted _SIGNATURE"""
+                # make catalog
+                c = catalog.Catalog(meta_root=self.test_root)
+                c.save()
+
+                # corrupt it
+                fname = os.path.join(self.test_root, "catalog.attrs")
+                f = open(fname, "r")
+                struct = simplejson.load(f)
+                f.close()
+                # corrupt signature by one digit
+                sig = int(struct["_SIGNATURE"]["sha-1"], 16)
+                struct["_SIGNATURE"]["sha-1"] = "%x" % (sig + 1)
+                f = open(fname, "w")
+                print >> f, simplejson.dumps(struct)
+                f.close()
+
+                c = catalog.Catalog(meta_root=self.test_root)
+                self.assertRaises(api_errors.BadCatalogSignatures, c.validate,
+                    require_signatures=True)
+                self.assertRaises(api_errors.BadCatalogSignatures, c.validate,
+                    require_signatures=False)
+
+        def test_corrupt_attrs5(self):
+                """Raise BadCatalogSignatures for a catalog.attrs with
+                missing _SIGNATURE"""
+                # make catalog
+                c = catalog.Catalog(meta_root=self.test_root)
+                c.save()
+
+                # corrupt it by removing _SIGNATURE
+                fname = os.path.join(self.test_root, "catalog.attrs")
+                f = open(fname, "r")
+                struct = simplejson.load(f)
+                f.close()
+                del struct["_SIGNATURE"]
+                f = open(fname, "w")
+                print >> f, simplejson.dumps(struct)
+                f.close()
+
+                c = catalog.Catalog(meta_root=self.test_root)
+                # Catalog should validate unless require_signatures=True
+                c.validate()
+                self.assertRaises(api_errors.BadCatalogSignatures, c.validate,
+                    require_signatures=True)
+
+        def test_corrupt_attrs6(self):
+                """Raise UnrecognizedCatalogPart for a catalog.attrs{parts}
+                with bogus subpart."""
+                # make catalog
+                c = catalog.Catalog(meta_root=self.test_root)
+                c.save()
+
+                # corrupt it by adding a bad name to the set of parts.
+                fname = os.path.join(self.test_root, "catalog.attrs")
+                f = open(fname, "r")
+                struct = simplejson.load(f)
+                f.close()
+                struct["parts"]["/badpartname/"] = {}
+                f = open(fname, "w")
+                print >> f, simplejson.dumps(struct)
+                f.close()
+
+                # Catalog constructor should reject busted 'parts'
+                self.assertRaises(api_errors.UnrecognizedCatalogPart,
+                    catalog.Catalog, meta_root=self.test_root)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/api/t_linked_image.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_linked_image.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -796,7 +796,7 @@
                 api_objs[1].gen_plan_change_varcets(
                     variants={"variant.foo": "baz"})
 
-                # install a synced package into 1
+                # install a synced package into 0
                 self._api_install(api_objs[0], [self.p_sync1_name[2]],
                     li_ignore=[])
 
@@ -978,10 +978,12 @@
                         [self.p_sync1_name_gen])
 
                 # test operations on child nodes
-                rvdict = {1: EXIT_NOP, 2: EXIT_OOPS, 3: EXIT_OOPS,
+                rvdict = {1: EXIT_OK, 2: EXIT_OOPS, 3: EXIT_OOPS,
                     4: EXIT_OOPS}
                 self._children_op(0, [], "sync_linked_children",
                     rvdict=rvdict)
+                rvdict = {1: EXIT_NOP, 2: EXIT_OOPS, 3: EXIT_OOPS,
+                    4: EXIT_OOPS}
                 self._children_op(0, [1, 2, 3, 4], "sync_linked_children",
                     rvdict=rvdict)
 
--- a/src/tests/api/t_manifest.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_manifest.py	Wed Aug 14 11:12:35 2013 +0530
@@ -33,6 +33,7 @@
 import pkg as pkg
 import pkg.client.api_errors as api_errors
 import pkg.manifest as manifest
+import pkg.misc as misc
 import pkg.actions as actions
 import pkg.fmri as fmri
 import pkg.variant as variant
@@ -411,6 +412,19 @@
                 m1.exclude_content([v.allow_action, lambda x: True])
                 self.assertEqual(len(list(m1.gen_actions_by_type("dir"))), 1)
 
+        def test_store_to_disk(self):
+                """Verfies that a FactoredManifest gets force-loaded before it
+                gets stored to disk."""
+ 
+                m1 = manifest.FactoredManifest("[email protected]", self.cache_dir,
+                    pathname=self.foo_content_p5m)
+
+                tmpdir = tempfile.mkdtemp(dir=self.test_root)
+                path = os.path.join(tmpdir, "manifest.p5m")
+                m1.store(path)
+                self.assertEqual(misc.get_data_digest(path),
+                    misc.get_data_digest(self.foo_content_p5m))
+
         def test_get_directories(self):
                 """Verifies that get_directories() works as expected."""
 
--- a/src/tests/api/t_pkg_api_install.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_pkg_api_install.py	Wed Aug 14 11:12:35 2013 +0530
@@ -955,7 +955,7 @@
 
                                 bad_mdata = mdata.replace(src_mode, bad_mode)
                                 self.write_img_manifest(pfmri, bad_mdata)
-                                DebugValues["skip-verify-manifest"] = "True"
+                                DebugValues["manifest_validate"] = "Never"
                                 self.assertRaises(api_errors.InvalidPackageErrors,
                                     self.__do_install, api_obj,
                                     [pfmri.pkg_name])
--- a/src/tests/api/t_pkglint.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/api/t_pkglint.py	Wed Aug 14 11:12:35 2013 +0530
@@ -33,6 +33,7 @@
 import unittest
 import tempfile
 
+import pkg.lint.base as base
 import pkg.lint.engine as engine
 import pkg.lint.log as log
 import pkg.fmri as fmri
@@ -2058,6 +2059,23 @@
 file path=usr/perl5/5.12/bin/perl owner=root group=sys mode=0755
 """
 
+expected_failures["noversion-incorp.mf" ] = ["pkglint.action011"]
+broken_manifests["noversion-incorp.mf" ] = \
+"""
+#
+# We deliver an 'incorporate' dependency without specifying the version.
+#
+set name=pkg.fmri value=pkg://opensolaris.org/pkglint/[email protected],1.0
+set name=org.opensolaris.consolidation value=osnet
+set name=variant.opensolaris.zone value=global value=nonglobal
+set name=pkg.description value="A pkglint test"
+set name=pkg.summary value="Yet another test"
+set name=variant.arch value=i386 value=sparc
+set name=info.classification value=org.opensolaris.category.2008:System/Packaging
+depend type=incorporate fmri=pkg:/some/package
+"""
+
+
 class TestLogFormatter(log.LogFormatter):
         """Records log messages to a buffer"""
         def __init__(self):
@@ -3106,6 +3124,127 @@
                     "Expected pkglint.dupaction001.1, got %s" %
                     lint_logger.ids[0])
 
+
+class TestVolatileLintEngineDepot(pkg5unittest.ManyDepotTestCase):
+        """Tests that exercise reference vs. lint repository checks and tests
+        linting of multiple packages at once, similar to TestLintEngineDepot,
+        but with less overhead during setUp (this test class is not marked
+        as persistent_setup = True, so test methods are responsible for their
+        own setup)"""
+
+        # used by test_get_manifest(..)
+        get_manifest_data = {}
+# The following two manifests check that given a package in the lint repository,
+# that we can access the latest version of that package from the reference
+# repository using LintEngine.get_manifest(.., reference=True)
+        get_manifest_data["get-manifest-ref.mf"] = """
+set name=pkg.fmri value=pkg://opensolaris.org/check/[email protected],5.11-0.100:20100603T215050Z
+set name=variant.arch value=i386 value=sparc
+set name=pkg.summary value="additional content"
+set name=pkg.description value="core kernel software for a specific instruction-set architecture"
+set name=org.opensolaris.consolidation value=osnet
+set name=info.classification value=org.opensolaris.category.2008:System/Core
+"""
+        get_manifest_data["get-manifest-oldref.mf"] = """
+set name=pkg.fmri value=pkg://opensolaris.org/check/[email protected],5.11-0.99:20100603T215050Z
+set name=variant.arch value=i386 value=sparc
+set name=pkg.summary value="additional content"
+set name=pkg.description value="core kernel software for a specific instruction-set architecture"
+set name=org.opensolaris.consolidation value=osnet
+set name=info.classification value=org.opensolaris.category.2008:System/Core
+"""
+        get_manifest_data["get-manifest-lint.mf"] = """
+#
+# This is the manifest that should appear in the lint repository.
+#
+set name=variant.arch value=i386 value=sparc
+set name=pkg.summary value="additional content"
+set name=pkg.fmri value=pkg://opensolaris.org/check/[email protected],5.11-0.145:20100603T215050Z
+set name=pkg.description value="core kernel software for a specific instruction-set architecture"
+set name=org.opensolaris.consolidation value=osnet
+set name=info.classification value=org.opensolaris.category.2008:System/Core
+"""
+
+        def setUp(self):
+                pkg5unittest.ManyDepotTestCase.setUp(self,
+                    ["opensolaris.org", "opensolaris.org"],
+                    start_depots=True)
+
+                self.ref_uri = self.dcs[1].get_depot_url()
+                self.lint_uri = self.dcs[2].get_depot_url()
+                self.cache_dir = tempfile.mkdtemp("pkglint-cache", "",
+                    self.test_root)
+
+        def test_get_manifest(self):
+                """Check that <LintEngine>.get_manifest works ensuring
+                it returns appropriate manifests for the lint and reference
+                repositories."""
+
+                paths = self.make_misc_files(self.get_manifest_data)
+                rcfile = os.path.join(self.test_root, "pkglintrc")
+                lint_mf = os.path.join(self.test_root, "get-manifest-lint.mf")
+                old_ref_mf = os.path.join(self.test_root,
+                    "get-manifest-oldref.mf")
+                ref_mf = os.path.join(self.test_root, "get-manifest-ref.mf")
+                ret, ref_fmri =  self.pkgsend(self.ref_uri, "publish %s" %
+                    ref_mf)
+                ret, oldref_fmri =  self.pkgsend(self.ref_uri, "publish %s" %
+                    old_ref_mf)
+                ret, lint_fmri =  self.pkgsend(self.lint_uri, "publish %s" %
+                    lint_mf)
+
+                lint_logger = TestLogFormatter()
+                lint_engine = engine.LintEngine(lint_logger, use_tracker=False,
+                    config_file=rcfile)
+                manifests = read_manifests([lint_mf], lint_logger)
+                lint_engine.setup(cache=self.cache_dir,
+                    ref_uris=[self.ref_uri], lint_uris=[self.lint_uri])
+
+                # try retrieving a few names that should match our lint manifest
+                for name in ["check/parent", "pkg:/check/parent",
+                    "pkg://opensolaris.org/check/[email protected]"]:
+                        mf = lint_engine.get_manifest(
+                            name, search_type=lint_engine.LATEST_SUCCESSOR)
+                        self.assert_(str(mf.fmri) == lint_fmri)
+
+                # try retrieving a few names that should match our parent
+                # manifest when using LATEST_SUCCESSOR mode
+                for name in ["check/parent", "pkg:/check/parent",
+                    "pkg://opensolaris.org/check/[email protected]"]:
+                        mf = lint_engine.get_manifest(
+                            name, search_type=lint_engine.LATEST_SUCCESSOR,
+                            reference=True)
+                        self.assert_(str(mf.fmri) == ref_fmri)
+
+                # try retrieving a few names that should not match when using
+                # EXACT mode.
+                for name in ["check/[email protected]",
+                    "pkg://opensolaris.org/check/[email protected]"]:
+                        mf = lint_engine.get_manifest(
+                            name, search_type=lint_engine.EXACT)
+                        self.assert_(mf == None)
+
+                # try retrieving a specific version of the manifest from the
+                # reference repository.
+                mf = lint_engine.get_manifest(
+                    "pkg://opensolaris.org/check/[email protected],5.11-0.99",
+                    search_type=lint_engine.EXACT, reference=True)
+                self.assert_(str(mf.fmri) == oldref_fmri)
+
+                # test that we raise an exception when no reference repo is
+                # configured, but that searches for a non-existent package from
+                # the lint manifests do still return None.
+                shutil.rmtree(os.path.join(self.cache_dir, "ref_image"))
+                lint_engine = engine.LintEngine(lint_logger, use_tracker=False,
+                    config_file=rcfile)
+                lint_engine.setup(cache=self.cache_dir,
+                    lint_manifests=manifests)
+                mf = lint_engine.get_manifest("example/package")
+                self.assert_(mf == None)
+                self.assertRaises(base.LintException, lint_engine.get_manifest,
+                    "example/package", reference=True)
+
+
 class TestLintEngineInternals(pkg5unittest.Pkg5TestCase):
 
         def test_lint_fmri_successor(self):
--- a/src/tests/cli/t_actuators.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_actuators.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -29,7 +29,7 @@
 import os
 import pkg5unittest
 import unittest
-
+import stat
 class TestPkgSMFActuators(pkg5unittest.SingleDepotTestCase):
         # Only start/stop the depot once (instead of for every test)
         persistent_setup = True
@@ -468,19 +468,21 @@
             add file tmp/release-note-6 mode=0644 owner=root group=root path=/usr/share/doc/release-notes/release-note-6 release-note=feature/pkg/self@0
             close """
 
+        multi_unicode = u"Eels are best smoked\nМоё судно на воздушной подушке полно угрей\nHovercraft can be smoked, too.\n"
+        multi_ascii = "multi-line release notes\nshould work too,\nwe'll see if they do.\n"
         misc_files = {
                 "tmp/release-note-1":"bobcats are fun!",
                 "tmp/release-note-2":"wombats are fun!",
                 "tmp/release-note-3":"no animals were hurt...",
                 "tmp/release-note-4":"no vegetables were hurt...",
-                "tmp/release-note-5":"multi-line release notes\nshould work too,\nwe'll see if they do.",
-                "tmp/release-note-6":u"Eels are best smoked\nМоё судно на воздушной подушке полно угрей\nHovercraft can be smoked, too.\n",
+                "tmp/release-note-5":multi_ascii,
+                "tmp/release-note-6":multi_unicode
                 }
 
         def setUp(self):
                 pkg5unittest.SingleDepotTestCase.setUp(self)
                 self.make_misc_files(self.misc_files)
-                self.pkgsend_bulk(self.rurl, self.foo10 + self.foo11 + 
+                self.pkgsend_bulk(self.rurl, self.foo10 + self.foo11 +
                     self.foo12 + self.foo13 + self.bar10 + self.bar11 + self.baz10 +
                     self.hovercraft)
                 self.image_create(self.rurl)
@@ -499,9 +501,9 @@
                 # but that user is prompted that notes are available.
                 self.pkg("update [email protected]")
                 assert self.output.find("no vegetables") == -1
+                self.pkg("uninstall '*'")
 
         def test_release_note_2(self):
-                self.pkg("uninstall '*'")
                 # check that release notes are printed with just -n
                 self.pkg("install -vn [email protected]")
                 self.output.index("bobcats are fun!")
@@ -518,11 +520,11 @@
                 # check that we say yes that release notes are available
                 self.pkg("history -Hn 1 -o release_notes")
                 self.output.index("Yes")
+                self.pkg("uninstall '*'")
 
         def test_release_note_3(self):
                 # check that release notes are printed properly
                 # when needed and dependency is on other pkg
-                self.pkg("uninstall '*'")
                 self.pkg("install [email protected]")
                 self.pkg("install -v [email protected]")
                 self.output.index("multi-line release notes")
@@ -535,27 +537,91 @@
                 # no output expected here since [email protected] isn't part of original image.
                 self.pkg("install [email protected] [email protected]")
                 assert self.output.find("multi-line release notes") == -1
+                self.pkg("uninstall '*'")
 
         def test_release_note_4(self):
                 # make sure that parseable option works properly
-                self.pkg("uninstall '*'")                
                 self.pkg("install [email protected]")
                 self.pkg("install --parsable 0 [email protected]")
                 self.output.index("multi-line release notes")
                 self.output.index("should work too,")
                 self.output.index("we'll see if they do.")
                 self.pkg("uninstall '*'")
-                # test unicode character in files
+
+        def test_release_note_5(self):
+                # test unicode character in release notes
                 self.pkg("install -n [email protected]")
                 unicode(self.output, "utf-8").index(u"Моё судно на воздушной подушке полно угрей")
                 unicode(self.output, "utf-8").index(u"Eels are best smoked")
-                self.pkg("install -v [email protected]")                
+                self.pkg("install -v [email protected]")
+                unicode(self.output, "utf-8").index(u"Моё судно на воздушной подушке полно угрей")
+                unicode(self.output, "utf-8").index(u"Eels are best smoked")
+                self.pkg("uninstall '*'")
+
+        def test_release_note_6(self):
+                # test parsable unicode
+                self.pkg("install --parsable 0 [email protected]")
+                self.pkg("history -n 1 -N")
                 unicode(self.output, "utf-8").index(u"Моё судно на воздушной подушке полно угрей")
                 unicode(self.output, "utf-8").index(u"Eels are best smoked")
                 self.pkg("uninstall '*'")
-                self.pkg("install --parsable 0 [email protected]")                
-                self.pkg("history -n 1 -N")
-                unicode(self.output, "utf-8").index(u"Моё судно на воздушной подушке полно угрей")
-                unicode(self.output, "utf-8").index(u"Eels are best smoked")
+
+        def test_release_note_7(self):
+                # check that multiple release notes are composited properly
+                self.pkg("install [email protected]")
+                self.pkg("install -v [email protected] [email protected]")
+                uni_out = unicode(self.output, "utf-8")
+                # we indent the release notes for readability, so a strict
+                # index or compare won't work unless we remove indenting
+                # this works for our test cases since they have no leading
+                # spaces
+
+                # removing indent
+                uni_out = "\n".join((n.lstrip() for n in uni_out.split("\n")))
+
+                uni_out.index(self.multi_unicode)
+                uni_out.index(self.multi_ascii)
+
+		# repeat test using history to make sure everything is there.
+		# do as unpriv. user
+
+		self.pkg("history -n 1 -HN", su_wrap=True)
+                uni_out = unicode(self.output, "utf-8")
+                # we indent the release notes for readability, so a strict
+                # index or compare won't work unless we remove indenting
+                # this works for our test cases since they have no leading
+                # spaces
+
+                # removing indent
+                uni_out = "\n".join((n.lstrip() for n in uni_out.split("\n")))
+
+                uni_out.index(self.multi_unicode)
+                uni_out.index(self.multi_ascii)
+		
+                self.pkg("uninstall '*'")
+
+        def test_release_note_8(self):
+                # verify that temporary file is correctly written with /n characters
+                self.pkg("-D GenerateNotesFile=1 install [email protected]")
+                # find name of file containing release notes in output.
+                for field in unicode(self.output, "utf-8").split(u" "):
+                        try:
+                                if field.index(u"release-note"):
+                                        break
+                        except:
+                                pass
+                else:
+                        assert "output file not found" == 0
+
+                # make sure file is readable by everyone
+                assert(stat.S_IMODE(os.stat(field).st_mode) == 0644)
+
+                # read release note file and check to make sure
+                # entire contents are there verbatim
+                release_note = unicode(file(field).read(), "utf-8")
+                assert self.multi_unicode == release_note
+                self.pkg("uninstall '*'")
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_change_facet.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_change_facet.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -122,7 +122,7 @@
 
                 self.pkg_image_create(self.rurl, additional_args=ic_args)
                 self.pkg("facet")
-                self.pkg("facet -H 'facet.locale*' | egrep False")
+                self.pkg("facet -H -F tsv 'facet.locale*' | egrep False")
 
                 # install a package and verify
                 alist = [self.plist[0]]
@@ -145,8 +145,9 @@
                 # are in effect
                 self.pkg("change-facet -n --parsable=0 wombat=false")
                 self.assertEqualParsable(self.output,
-                    affect_packages=alist,
-                    change_facets=[["facet.wombat", False]])
+                    affect_packages=[],
+                    change_facets=[["facet.wombat", False, None, 'local',
+                       False, False]])
 
                 # Again, but this time after removing the publisher cache data
                 # and as an unprivileged user to verify that cached manifest
@@ -157,8 +158,9 @@
                 self.pkg("change-facet --no-refresh -n --parsable=0 "
                     "wombat=false", su_wrap=True)
                 self.assertEqualParsable(self.output,
-                    affect_packages=alist,
-                    change_facets=[["facet.wombat", False]])
+                    affect_packages=[],
+                    change_facets=[["facet.wombat", False, None, 'local',
+                        False, False]])
 
                 # Again, but this time after removing the cache directory
                 # entirely.
@@ -168,15 +170,17 @@
                 self.pkg("change-facet --no-refresh -n --parsable=0 "
                     "wombat=false", su_wrap=True)
                 self.assertEqualParsable(self.output,
-                    affect_packages=alist,
-                    change_facets=[["facet.wombat", False]])
+                    affect_packages=[],
+                    change_facets=[["facet.wombat", False, None, 'local',
+                        False, False]])
 
                 # change to pick up another file w/ two tags and test the
                 # parsable output
                 self.pkg("change-facet --parsable=0 facet.locale.nl_ZA=True")
                 self.assertEqualParsable(self.output,
                     affect_packages=alist,
-                    change_facets=[["facet.locale.nl_ZA", True]])
+                    change_facets=[["facet.locale.nl_ZA", True, None, 'local',
+                        False, False]])
                 self.pkg("verify")
                 self.pkg("facet")
 
@@ -195,9 +199,11 @@
                 self.assertEqualParsable(self.output,
                     affect_packages=alist,
                     change_facets=[
-                        ["facet.locale*", None],
-                        ["facet.locale.fr*", None],
-                        ["facet.locale.fr_CA", None]
+                        ["facet.locale*", None, False, 'local', False, False],
+                        ["facet.locale.fr*", None, True, 'local', False,
+                            False],
+                        ["facet.locale.fr_CA", None, False, 'local', False,
+                            False]
                     ])
                 self.pkg("verify")
 
@@ -225,9 +231,10 @@
                 self.assertEqualParsable(self.output,
                     affect_packages=alist,
                     change_facets=[
-                        ["facet.locale*", None],
-                        ["facet.locale.*", False],
-                        ["facet.locale.fr_CA", True]
+                        ["facet.locale*", None, False, 'local', False, False],
+                        ["facet.locale.*", False, None, 'local', False, False],
+                        ["facet.locale.fr_CA", True, None, 'local', False,
+                            False]
                     ])
                 self.assert_file_is_there("4")
 
@@ -238,9 +245,11 @@
                 self.assertEqualParsable(self.output,
                     affect_packages=alist,
                     change_facets=[
-                        ["facet.locale.*", None],
-                        ["facet.locale.fr_*", False],
-                        ["facet.locale.fr_CA", None]
+                        ["facet.locale.*", None, False, 'local', False, False],
+                        ["facet.locale.fr_*", False, None, 'local', False,
+                            False],
+                        ["facet.locale.fr_CA", None, True, 'local', False,
+                            False]
                     ])
                 self.assert_file_is_there("4")
 
@@ -252,11 +261,11 @@
                 # Test that setting a non-existent facet to True then removing
                 # it works.
                 self.pkg("change-facet -v foo=True")
-                self.pkg("facet -H")
-                self.assertEqual("facet.foo True\n", self.output)
+                self.pkg("facet -H -F tsv")
+                self.assertEqual("facet.foo\tTrue\tlocal\n", self.output)
                 self.pkg("change-facet --parsable=0 foo=None")
                 self.assertEqualParsable(self.output, change_facets=[
-                    ["facet.foo", None]])
+                    ["facet.foo", None, True, 'local', False, False]])
                 self.pkg("facet -H")
                 self.assertEqual("", self.output)
 
@@ -291,12 +300,11 @@
                 # install a random package and make sure we don't accidentally
                 # change facets.
                 self.pkg("install [email protected]")
-                self.pkg("facet -H")
-                output = self.reduceSpaces(self.output)
+                self.pkg("facet -H -F tsv")
                 expected = (
-                    "facet.locale.fr_FR False\n"
-                    "facet.locale.fr False\n")
-                self.assertEqualDiff(expected, output)
+                    "facet.locale.fr\tFalse\tlocal\n"
+                    "facet.locale.fr_FR\tFalse\tlocal\n")
+                self.assertEqualDiff(expected, self.output)
                 for i in [ 0, 3, 4, 5, 6, 7 ]:
                         self.assert_file_is_there(str(i))
                 for i in [ 1, 2 ]:
@@ -306,12 +314,11 @@
                 # update an image and make sure we don't accidentally change
                 # facets.
                 self.pkg("update")
-                self.pkg("facet -H")
-                output = self.reduceSpaces(self.output)
+                self.pkg("facet -H -F tsv")
                 expected = (
-                    "facet.locale.fr_FR False\n"
-                    "facet.locale.fr False\n")
-                self.assertEqualDiff(expected, output)
+                    "facet.locale.fr\tFalse\tlocal\n"
+                    "facet.locale.fr_FR\tFalse\tlocal\n")
+                self.assertEqualDiff(expected, self.output)
                 for i in [ 0, 3, 4, 5, 6, 7 ]:
                         self.assert_file_is_there(str(i))
                 for i in [ 1, 2 ]:
@@ -333,10 +340,10 @@
 
                 # set a facet on an image with no facets
                 self.pkg("change-facet -v locale.fr=False")
-                self.pkg("facet -H")
+                self.pkg("facet -H -F tsv")
                 output = self.reduceSpaces(self.output)
                 expected = (
-                    "facet.locale.fr False\n")
+                    "facet.locale.fr\tFalse\tlocal\n")
                 self.assertEqualDiff(expected, output)
                 for i in [ 0, 2, 3, 4, 5, 6, 7 ]:
                         self.assert_file_is_there(str(i))
@@ -346,12 +353,11 @@
 
                 # set a facet on an image with existing facets
                 self.pkg("change-facet -v locale.fr_FR=False")
-                self.pkg("facet -H")
-                output = self.reduceSpaces(self.output)
+                self.pkg("facet -H -F tsv")
                 expected = (
-                    "facet.locale.fr_FR False\n"
-                    "facet.locale.fr False\n")
-                self.assertEqualDiff(expected, output)
+                    "facet.locale.fr\tFalse\tlocal\n"
+                    "facet.locale.fr_FR\tFalse\tlocal\n")
+                self.assertEqualDiff(expected, self.output)
                 for i in [ 0, 3, 4, 5, 6, 7 ]:
                         self.assert_file_is_there(str(i))
                 for i in [ 1, 2 ]:
@@ -361,11 +367,11 @@
                 # clear a facet while setting a facet on an image with other
                 # facets that aren't being changed
                 self.pkg("change-facet -v locale.fr=None locale.nl=False")
-                self.pkg("facet -H")
+                self.pkg("facet -H -F tsv")
                 output = self.reduceSpaces(self.output)
                 expected = (
-                    "facet.locale.fr_FR False\n"
-                    "facet.locale.nl False\n")
+                    "facet.locale.fr_FR\tFalse\tlocal\n"
+                    "facet.locale.nl\tFalse\tlocal\n")
                 self.assertEqualDiff(expected, output)
                 for i in [ 0, 1, 3, 4, 6, 7 ]:
                         self.assert_file_is_there(str(i))
@@ -376,10 +382,10 @@
                 # clear a facet on an image with other facets that aren't
                 # being changed
                 self.pkg("change-facet -v locale.nl=None")
-                self.pkg("facet -H")
+                self.pkg("facet -H -F tsv")
                 output = self.reduceSpaces(self.output)
                 expected = (
-                    "facet.locale.fr_FR False\n")
+                    "facet.locale.fr_FR\tFalse\tlocal\n")
                 self.assertEqualDiff(expected, output)
                 for i in [ 0, 1, 3, 4, 5, 6, 7 ]:
                         self.assert_file_is_there(str(i))
@@ -389,7 +395,7 @@
 
                 # clear the only facet on an image
                 self.pkg("change-facet -v locale.fr_FR=None")
-                self.pkg("facet -H")
+                self.pkg("facet -H -F tsv")
                 self.assertEqualDiff("", self.output)
                 for i in range(8):
                         self.assert_file_is_there(str(i))
--- a/src/tests/cli/t_change_variant.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_change_variant.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -32,6 +32,7 @@
 import re
 import unittest
 
+import pkg.misc as misc
 from pkg.client.pkgdefs import *
 
 class TestPkgChangeVariant(pkg5unittest.SingleDepotTestCase):
@@ -69,8 +70,19 @@
         add file tmp/pkg_shared/shared/nonglobal_motd mode=0555 owner=root group=bin path=shared/zone_motd variant.opensolaris.zone=nonglobal
         add file tmp/pkg_shared/unique/global mode=0555 owner=root group=bin path=unique/global variant.opensolaris.zone=global
         add file tmp/pkg_shared/unique/nonglobal mode=0555 owner=root group=bin path=unique/nonglobal variant.opensolaris.zone=nonglobal
+        close"""
 
-        close"""
+        pkg_unknown = """
+        open [email protected]
+        add set name=variant.unknown value=bar value=foo
+        add file tmp/bar path=usr/bin/bar mode=0755 owner=root group=root variant.unknown=bar
+        add file tmp/foo path=usr/bin/foo mode=0755 owner=root group=root variant.unknown=foo
+        close
+        open [email protected]
+        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 """
 
         # this package intentionally has no variant.arch specification.
         pkg_inc = """
@@ -109,7 +121,10 @@
             "tmp/pkg_shared/shared/global_motd",
             "tmp/pkg_shared/shared/nonglobal_motd",
             "tmp/pkg_shared/unique/global",
-            "tmp/pkg_shared/unique/nonglobal"
+            "tmp/pkg_shared/unique/nonglobal",
+
+            "tmp/bar",
+            "tmp/foo"
         ]
 
         def setUp(self):
@@ -117,7 +132,8 @@
 
                 self.make_misc_files(self.misc_files)
                 self.pkgsend_bulk(self.rurl, (self.pkg_i386, self.pkg_sparc,
-                    self.pkg_shared, self.pkg_inc, self.pkg_cluster))
+                    self.pkg_shared, self.pkg_inc, self.pkg_cluster,
+                    self.pkg_unknown))
 
                 # verify pkg search indexes
                 self.verify_search = True
@@ -125,6 +141,16 @@
                 # verify installed images before changing variants
                 self.verify_install = False
 
+        def __assert_variant_matches_tsv(self, expected, errout=None,
+            exit=0, opts=misc.EmptyI, names=misc.EmptyI, su_wrap=False):
+                self.pkg("variant %s -H -F tsv %s" % (" ".join(opts),
+                    " ".join(names)), exit=exit, su_wrap=su_wrap)
+                self.assertEqualDiff(expected, self.output)
+                if errout:
+                        self.assert_(self.errout != "")
+                else:
+                        self.assertEqualDiff("", self.errout)
+
         def f_verify(self, path, token=None, negate=False):
                 """Verify that the specified path exists and contains
                 the specified token.  If negate is true, then make sure
@@ -303,8 +329,12 @@
                     "variant.opensolaris.zone": v_zone
                 }
                 self.image_create(self.rurl, variants=variants)
-                self.pkg("variant -H| egrep %s" % ("'variant.arch[ ]*%s'" % v_arch))
-                self.pkg("variant -H| egrep %s" % ("'variant.opensolaris.zone[ ]*%s'" % v_zone))
+
+                exp_tsv = """\
+variant.arch\t%s
+variant.opensolaris.zone\t%s
+""" % (v_arch, v_zone)
+                self.__assert_variant_matches_tsv(exp_tsv)
 
                 # install the specified packages into the image
                 ii_args = ""
@@ -325,8 +355,11 @@
                 # verify the updated image
                 self.i_verify(v_arch2, v_zone2, pl2)
 
-                self.pkg("variant -H| egrep %s" % ("'variant.arch[ ]*%s'" % v_arch2))
-                self.pkg("variant -H| egrep %s" % ("'variant.opensolaris.zone[ ]*%s'" % v_zone2))
+                exp_tsv = """\
+variant.arch\t%s
+variant.opensolaris.zone\t%s
+""" % (v_arch2, v_zone2)
+                self.__assert_variant_matches_tsv(exp_tsv)
 
                 self.image_destroy()
 
@@ -428,6 +461,44 @@
                 self.cv_test("sparc", "global", ["pkg_cluster"],
                     "i386", "nonglobal", ["pkg_cluster"])
 
+        def test_cv_12_unknown(self):
+                """Ensure that packages with an unknown variant and
+                non-conflicting content can be installed and subsequently
+                altered using change-variant."""
+
+                self.image_create(self.rurl)
+
+                # Install package with unknown variant and verify both files are
+                # present.
+                self.pkg("install -v [email protected]")
+                for fname in ("bar", "foo"):
+                        self.f_verify("usr/bin/%s" % fname, fname)
+
+                # 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)
+
+                # Next, set unknown variant explicitly and verify content
+                # changes as expected.
+                self.pkg("change-variant unknown=foo")
+
+                # 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")
+
+                # Next, upgrade to version of package with conflicting content
+                # and verify content changes as expected.
+                self.pkg("update -vvv [email protected]")
+
+                # Verify bar and foo no longer exist...
+                for fname in ("bar", "foo"):
+                        self.f_verify("usr/bin/%s" % fname, fname, negate=True)
+
+                # ...and that foo variant of foobar is now installed.
+                self.f_verify("usr/bin/foobar", "foo")
+
         def test_cv_parsable(self):
                 """Test the parsable output of change-variant."""
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_depot_config.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,796 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+import pkg5unittest
+
+import copy
+import httplib
+import os
+import time
+import unittest
+import urllib2
+
+import pkg.fmri
+
+HTTPDEPOT_USER = "pkg5srv"
+
+class TestHttpDepot(pkg5unittest.ApacheDepotTestCase):
+        """Tests that exercise the pkg.depot-config CLI as well as checking the
+        functionality of the depot-config itself. This test class will
+        fail if not run as root, since many of the tests use 'pkg.depot-config -a'
+        which will attempt to chown a directory to pkg5srv:pkg5srv.
+
+        The default_svcs_conf having an instance name of 'usr' is not a
+        coincidence: we use it there so that we catch RewriteRules that
+        mistakenly try to serve content from the root filesystem ('/') rather
+        than from beneath our DocumentRoot (assuming that test systems always
+        have a /usr directory)
+        """
+
+        # An array that can be used to build our svcs(1) wrapper.
+        default_svcs_conf = [
+            # FMRI                                   STATE
+            ["svc:/application/pkg/server:default",  "online" ],
+            ["svc:/application/pkg/server:usr",      "online" ],
+            # repositories that we will not serve
+            ["svc:/application/pkg/server:off",      "offline"],
+            ["svc:/application/pkg/server:writable", "online" ],
+            ["svc:/application/pkg/server:solitary", "offline"]
+        ]
+
+        # An array that can be used to build our svcprop(1)
+        # wrapper in conjunction with svcs_conf.  This array
+        # must be in the same order as svcs_conf and the rows
+        # must correspond.
+        default_svcprop_conf = [
+            # inst_root           readonly  standalone
+            ["%(rdir1)s",         "true",   "false"   ],
+            ["%(rdir2)s",         "true",   "false"   ],
+            # we intentionally use non-existent repository
+            # paths in these services, and check they aren't
+            # present in the httpd.conf later.
+            ["/pkg5/there/aint", "true",    "false",   "offline"],
+            ["/pkg5/nobody/here", "false",   "false"  ],
+            ["/pkg5/but/us/chickens",  "true",    "true"   ],
+        ]
+
+        sample_pkg = """
+            open [email protected],5.11-0
+            add file tmp/sample mode=0444 owner=root group=bin path=/usr/bin/sample
+            close"""
+
+        sample_pkg_11 = """
+            open [email protected],5.11-0
+            add file tmp/updated mode=0444 owner=root group=bin path=/usr/bin/sample
+            close"""
+
+        new_pkg = """
+            open [email protected],5.11-0
+            add file tmp/new mode=0444 owner=root group=bin path=/usr/bin/new
+            close"""
+
+        another_pkg = """
+            open [email protected],5.11-0
+            add file tmp/another mode=0444 owner=root group=bin path=/usr/bin/another
+            close"""
+
+        carrots_pkg = """
+            open pkg://carrots/[email protected],5.11-0
+            add file tmp/another mode=0444 owner=root group=bin path=/usr/bin/carrots
+            close"""
+
+        misc_files = ["tmp/sample", "tmp/updated", "tmp/another", "tmp/new"]
+
+        def setUp(self):
+                self.sc = None
+                pkg5unittest.ApacheDepotTestCase.setUp(self, ["test1", "test2"])
+                self.rdir1 = self.dcs[1].get_repodir()
+                self.rdir2 = self.dcs[2].get_repodir()
+
+                self.default_depot_runtime = os.path.join(self.test_root,
+                    "depot_runtime")
+                self.default_depot_conf = os.path.join(
+                    self.default_depot_runtime, "depot_httpd.conf")
+                self.depot_conf_fragment = os.path.join(
+                    self.default_depot_runtime, "depot.conf")
+
+                self.depot_port = self.next_free_port
+                self.next_free_port += 1
+                self.make_misc_files(self.misc_files)
+                self.__set_smf_state()
+
+        def __set_smf_state(self, svcs_conf=default_svcs_conf,
+            svcprop_conf=default_svcprop_conf):
+                """Create wrapper scripts for svcprop and svcs based on the
+                arrays of arrays passed in as arguments. By default, the
+                following responses are configured using the class variables
+                svcs_conf and svcprop_conf:
+
+                pkg/server:default and pkg/server:usr can be served by the
+                depot-config as they are marked readonly=true, standalone=false.
+
+                pkg/server:off is ineligible, because it is reported as being
+                offline for these tests.
+                pkg/server:writable and pkg/server:solitary are both not
+                eligible to be served by the depot, the former, because it
+                is not marked as readonly, the latter because it is marked
+                as standalone.
+                """
+
+                # we don't want to modify our arguments
+                _svcs_conf = copy.deepcopy(svcs_conf)
+                _svcprop_conf = copy.deepcopy(svcprop_conf)
+
+                # ensure the arrays are the same length.
+                self.assert_(len(_svcs_conf) == len(_svcprop_conf))
+
+                for index, conf in enumerate(_svcs_conf):
+                        fmri = conf[0]
+                        state = conf[1]
+                        _svcprop_conf[index].insert(0, fmri)
+                        _svcprop_conf[index].insert(1, state)
+
+                rdirs = {"rdir1": self.rdir1, "rdir2": self.rdir2}
+
+                # construct two strings we can use as parameters to our
+                # __svc*_template values
+                _svcs_conf = " ".join(["%".join([value for value in item])
+                    for item in _svcs_conf])
+                _svcprop_conf = " ".join(["%".join(
+                    [value % rdirs for value in item])
+                    for item in _svcprop_conf])
+
+                self.smf_cmds = {
+                    "usr/bin/svcs": self.__svcs_template % _svcs_conf,
+                    "usr/bin/svcprop": self.__svcprop_template % _svcprop_conf
+                }
+                self.make_misc_files(self.smf_cmds, "smf_cmds", mode=0755)
+
+        def start_depot(self, build_indexes=True):
+                hc = pkg5unittest.HttpDepotController(
+                    self.default_depot_conf, self.depot_port,
+                    self.default_depot_runtime, testcase=self)
+                self.register_apache_controller("depot", hc)
+                self.ac.start()
+                if build_indexes:
+                        # we won't return until indexes are built
+                        u = urllib2.urlopen(
+                            "%s/depot/depot-wait-refresh" % hc.url).close()
+
+        def test_0_htdepot(self):
+                """A basic test to see that we can start the depot,
+                as part of this, by starting the depot, ApacheController will
+                ping the "/ URI of the server."""
+
+                # ensure we fail when not supplying the required argument
+                self.depotconfig("", exit=2, fill_missing_args=False)
+                self.depotconfig("")
+                self.start_depot()
+
+                # the httpd.conf should reference our repositories
+                self.file_contains(self.ac.conf, self.rdir1)
+                self.file_contains(self.ac.conf, self.rdir2)
+                # it should not reference the repositories that we have
+                # marked as offline, writable or standalone
+                self.file_doesnt_contain(self.ac.conf, "/pkg5/there/aint")
+                self.file_doesnt_contain(self.ac.conf, "/pkg5/nobody/here")
+                self.file_doesnt_contain(self.ac.conf, "/pkg5/but/us/chickens")
+
+        def test_1_htdepot_usage(self):
+                """Tests that we show a usage message."""
+
+                ret, output = self.depotconfig("", fill_missing_args=False,
+                    out=True, exit=2)
+                self.assert_("Usage:" in output,
+                    "No usage string printed: %s" % output)
+                ret, output = self.depotconfig("--help", out=True, exit=2)
+                self.assert_("Usage:" in output,
+                    "No usage string printed: %s" % output)
+
+        def test_2_htinvalid_root(self):
+                """We return an error given an invalid image root"""
+
+                # check for incorrectly-formed -d options
+                self.depotconfig("-d usr -F -r /dev/null", exit=2)
+
+                # ensure we pick up invalid -d directories
+                for invalid_root in ["usr=/dev/null",
+                    "foo=/etc/passwd", "alt=/proc"]:
+                        ret, output, err = self.depotconfig(
+                            "-d %s -F" % invalid_root, out=True, stderr=True,
+                            exit=1)
+                        expected = invalid_root.split("=")[1]
+                        self.assert_(expected in err,
+                            "error message did not contain %s: %s" %
+                            (expected, err))
+
+                # ensure we also catch invalid SMF inst_roots
+                svcs_conf = [["svc:/application/pkg/server:default", "online" ]]
+                svcprop_conf = [["/tmp", "true", "false"]]
+                self.__set_smf_state(svcs_conf, svcprop_conf)
+                ret, output, err = self.depotconfig("", out=True, stderr=True,
+                    exit=1)
+                self.assert_("/tmp" in err, "error message did not contain "
+                    "/tmp")
+
+        def test_3_invalid_htcache_dir(self):
+                """We return an error given an invalid cache_dir"""
+
+                for invalid_cache in ["/dev/null", "/etc/passwd"]:
+                        ret, output, err = self.depotconfig("-c %s" %
+                            invalid_cache, out=True, stderr=True, exit=1)
+                        self.assert_(invalid_cache in err, "error message "
+                            "did not contain %s: %s" % (invalid_cache, err))
+
+        def test_4_invalid_hthostname(self):
+                """We return an error given an invalid hostname"""
+
+                for invalid_host in ["1.2.3.4.5.6", "pkgsysrepotestname", "."]:
+                        ret, output, err = self.depotconfig("-h %s" %
+                            invalid_host, out=True, stderr=True, exit=1)
+                        self.assert_(invalid_host in err, "error message "
+                            "did not contain %s: %s" % (invalid_host, err))
+
+        def test_5_invalid_htlogs_dir(self):
+                """We return an error given an invalid logs_dir"""
+
+                for invalid_log in ["/dev/null", "/etc/passwd"]:
+                        ret, output, err = self.depotconfig("-l %s" % invalid_log,
+                            out=True, stderr=True, exit=1)
+                        self.assert_(invalid_log in err, "error message "
+                            "did not contain %s: %s" % (invalid_log, err))
+
+                for invalid_log in ["/proc"]:
+                        port = self.next_free_port
+                        self.depotconfig("-l %s -p %s" % (invalid_log, port),
+                            exit=0)
+                        self.assertRaises(pkg5unittest.ApacheStateException,
+                            self.start_depot)
+
+        def test_6_invalid_htport(self):
+                """We return an error given an invalid port"""
+
+                for invalid_port in [999999, "bobcat", "-1234"]:
+                        ret, output, err = self.depotconfig("-p %s" % invalid_port,
+                            out=True, stderr=True, exit=1)
+                        self.assert_(str(invalid_port) in err, "error message "
+                            "did not contain %s: %s" % (invalid_port, err))
+
+        def test_7_invalid_htruntime_dir(self):
+                """We return an error given an invalid runtime_dir"""
+
+                for invalid_runtime in ["/dev/null", "/etc/passwd", "/proc"]:
+                        ret, output, err = self.depotconfig("-r %s" %
+                            invalid_runtime, out=True, stderr=True, exit=1)
+                        self.assert_(invalid_runtime in err, "error message "
+                            "did not contain %s: %s" % (invalid_runtime, err))
+
+        def test_8_invalid_htcache_size(self):
+                """We return an error given an invalid cache_size"""
+
+                for invalid_csize in ["cats", "-1234"]:
+                        ret, output, err = self.depotconfig(
+                            "-s %s" % invalid_csize, out=True, stderr=True,
+                            exit=1)
+                        self.assert_(str(invalid_csize) in err, "error message "
+                            "did not contain %s: %s" % (invalid_csize, err))
+
+        def test_9_invalid_httemplates_dir(self):
+                """We return an error given an invalid templates_dir"""
+
+                for invalid_tmp in ["/dev/null", "/etc/passwd", "/proc"]:
+                        ret, output, err = self.depotconfig("-T %s" % invalid_tmp,
+                            out=True, stderr=True, exit=1)
+                        self.assert_(invalid_tmp in err, "error message "
+                            "did not contain %s: %s" % (invalid_tmp, err))
+
+        def test_9_invalid_httemplates_dir(self):
+                """We return an error given an invalid templates_dir"""
+
+                for invalid_tmp in ["/dev/null", "/etc/passwd", "/proc"]:
+                        ret, output, err = self.depotconfig("-T %s" % invalid_tmp,
+                            out=True, stderr=True, exit=1)
+                        self.assert_(invalid_tmp in err, "error message "
+                            "did not contain %s: %s" % (invalid_tmp, err))
+
+        def test_10_httype(self):
+                """We return an error given an invalid type option."""
+
+                invalid_type = "weblogic"
+                ret, output, err = self.depotconfig("-t %s" % invalid_type,
+                    out=True, stderr=True, exit=2)
+                self.assert_(invalid_type in err, "error message "
+                    "did not contain %s: %s" % (invalid_type, err))
+                # ensure we work with the supported type
+                self.depotconfig("-t apache2")
+
+        def test_11_htbui(self):
+                """We can perform a series of HTTP requests against the BUI."""
+
+                fmris = self.pkgsend_bulk(self.dcs[1].get_repo_url(),
+                    self.new_pkg)
+                self.depotconfig("")
+                self.start_depot()
+
+                fmri = pkg.fmri.PkgFmri(fmris[0])
+                esc_full_fmri = fmri.get_url_path()
+
+                conf = {"prefix": "default",
+                    "esc_full_fmri": esc_full_fmri}
+
+                # a series of BUI paths we should be able to access
+                paths = [
+                        "/",
+                        "/default/test1",
+                        "/default/en",
+                        "/default/en/index.shtml",
+                        "/default/en/catalog.shtml",
+                        "/default/p5i/0/new.p5i",
+                        "/default/info/0/%(esc_full_fmri)s",
+                        "/default/test1/info/0/%(esc_full_fmri)s",
+                        "/default/manifest/0/%(esc_full_fmri)s",
+                        "/default/en/search.shtml",
+                        "/usr/test2/en/catalog.shtml",
+                        "/depot/default/en/search.shtml?token=pkg&action=Search"
+                ]
+
+                for p in paths:
+                        url_path = "%s%s" % (self.ac.url, p % conf)
+                        try:
+                                url_obj = urllib2.urlopen(url_path)
+                                self.assert_(url_obj.code == 200,
+                                    "Failed to open %s: %s" % (url_path,
+                                    url_obj.code))
+                        except urllib2.HTTPError, e:
+                                self.debug("Failed to open %s: %s" %
+                                    (url_path, e))
+                                raise
+
+        def test_12_htpkgclient(self):
+                """A depot-config can act as a repository server for pkg(1)
+                clients, with all functionality supported."""
+
+                # publish some sample packages to our repositories
+                for dc_num in self.dcs:
+                        rurl = self.dcs[dc_num].get_repo_url()
+                        self.pkgsend_bulk(rurl, self.sample_pkg)
+                        self.pkgsend_bulk(rurl, self.sample_pkg_11)
+                self.pkgsend_bulk(self.dcs[2].get_repo_url(), self.new_pkg)
+
+                self.depotconfig("")
+                self.image_create()
+                self.start_depot()
+                # test that we can access the default publisher
+                self.pkg("set-publisher -p %s/default" % self.ac.url)
+                self.pkg("publisher")
+                self.pkg("install [email protected]")
+                self.file_contains("usr/bin/sample", "tmp/sample")
+                self.pkg("update")
+                self.file_contains("usr/bin/sample", "tmp/updated")
+
+                # test that we can access specific publishers, this time from
+                # a different repository, served by the same depot-config.
+                self.pkg("set-publisher -p %s/usr/test2" % self.ac.url)
+                self.pkg("contents -r new")
+                self.pkg("set-publisher -G '*' test2")
+                ret, output = self.pkg(
+                    "search -o action.raw -s %s/usr new" % self.ac.url,
+                    out=True)
+                self.assert_("path=usr/bin/new" in output)
+
+                # publish a new package, and ensure we can install it
+                self.pkgsend_bulk(self.dcs[1].get_repo_url(), self.another_pkg)
+                self.pkg("install another")
+                self.file_contains("usr/bin/another", "tmp/another")
+
+                # add a new publisher to an existing repository and ensure it
+                # is visible from the repository
+                self.ac.stop()
+                self.pkgrepo("-s %s add-publisher carrots" % self.rdir1)
+                self.pkgsend_bulk(self.dcs[1].get_repo_url(), self.carrots_pkg)
+                self.depotconfig("")
+                self.start_depot()
+
+                self.pkg("set-publisher -g %s/default/carrots carrots" %
+                    self.ac.url)
+
+        def test_13_htpkgrecv(self):
+                """A depot-config can act as a repository server for pkgrecv(1)
+                clients."""
+
+                rurl = self.dcs[1].get_repo_url()
+                first = self.pkgsend_bulk(rurl, self.sample_pkg)
+                second = self.pkgsend_bulk(rurl, self.sample_pkg_11)
+                self.pkgsend_bulk(self.dcs[2].get_repo_url(), self.new_pkg)
+
+                # gather the FMRIs we published and the URL-quoted version
+                first_fmri = pkg.fmri.PkgFmri(first[0])
+                second_fmri = pkg.fmri.PkgFmri(second[0])
+                first_ver = urllib2.quote(str(first_fmri.version))
+                second_ver = urllib2.quote(str(second_fmri.version))
+
+                self.depotconfig("")
+                self.image_create()
+                self.start_depot()
+
+                ret, output = self.pkgrecv(command="-s %s/default --newest" %
+                    self.ac.url, out=True)
+                self.assert_(str(second[0]) in output)
+                dest = os.path.join(self.test_root, "test_13_hgpkgrecv")
+                os.mkdir(dest)
+
+                # pull down raw package contents
+                self.pkgrecv(command="-s %s/default -m all-versions --raw "
+                    "-d %s '*'" % (self.ac.url, dest))
+
+                # Quickly sanity check the contents
+                self.assert_(os.listdir(dest) == ["sample"])
+                self.assert_(
+                    set(os.listdir(os.path.join(dest, "sample"))) ==
+                    set([first_ver, second_ver]))
+
+                # grab one of the manifests we just downloaded, and check that
+                # the file content is present and correct.
+                mf_path = os.path.sep.join([dest, "sample", second_ver])
+                mf = pkg.manifest.Manifest()
+                mf.set_content(pathname=os.path.join(mf_path, "manifest.file"))
+                f_ac = mf.actions[0]
+                self.assert_(f_ac.attrs["path"] == "usr/bin/sample")
+                f_path = os.path.join(mf_path, f_ac.hash)
+                os.path.exists(f_path)
+                self.file_contains(f_path, "tmp/updated")
+
+        def test_14_htpkgrepo(self):
+                """Test that only the 'pkgrepo refresh' command works with the
+                depot-config only when the -A flag is enabled. Test that
+                the index does indeed get updated when a refresh is performed
+                and that new package contents are visible."""
+
+                rurl = self.dcs[1].get_repo_url()
+                self.pkgsend_bulk(rurl, self.sample_pkg)
+                # allow index refreshes
+                self.depotconfig("-A")
+                self.start_depot()
+                self.image_create()
+                depot_url = "%s/default" % self.ac.url
+
+                # verify that list commands work
+                ret, output = self.pkgrepo("-s %s list -F tsv" % depot_url,
+                    out=True)
+                self.assert_("pkg://test1/[email protected]" in output)
+                self.assert_("pkg://test1/[email protected]" not in output)
+
+                # rebuild, remove and set commands should fail, the latter two
+                # with exit code 2
+                self.pkgrepo("-s %s rebuild" % depot_url, exit=1)
+                self.pkgrepo("-s %s remove sample" % depot_url, exit=2)
+                self.pkgrepo("-s %s set -p test1 foo/bar=baz" % depot_url,
+                    exit=2)
+
+                # verify search works for packages in the repository
+                self.pkg("set-publisher -p %s" % depot_url)
+                self.pkg("search -s %s msgsh" % "%s" % depot_url,
+                    exit=1)
+                self.pkg("search -s %s /usr/bin/sample" % depot_url)
+
+                # publish a new package, and verify it doesn't appear in the
+                # search results
+                self.pkgsend_bulk(rurl, self.new_pkg)
+                self.pkg("search -s %s /usr/bin/new" % depot_url, exit=1)
+
+                # refresh the index
+                self.pkgrepo("-s %s refresh" % depot_url)
+                # there isn't a synchronous option to pkgrepo, so wait a bit
+                # then make sure we do see this new package.
+                time.sleep(3)
+                ret, output = self.pkg("search -s %s /usr/bin/new" % depot_url,
+                    out=True)
+                self.assert_("usr/bin/new" in output)
+                ret, output = self.pkgrepo("-s %s list -F tsv" % depot_url,
+                    out=True)
+                self.assert_("pkg://test1/[email protected]" in output)
+                self.assert_("pkg://test1/[email protected]" in output)
+
+                # ensure that refresh --no-catalog works, but refresh --no-index
+                # does not.
+                self.pkgrepo("-s %s refresh --no-catalog" % depot_url)
+                self.pkgrepo("-s %s refresh --no-index" % depot_url, exit=1)
+
+                # check that when we start the depot without -A, we cannot
+                # issue refresh commands.
+                self.depotconfig("")
+                self.start_depot()
+                self.pkgrepo("-s %s refresh" % depot_url, exit=1)
+
+        def test_15_htheaders(self):
+                """Test that the correct Content-Type and Cache-control headers
+                are sent from the depot for the responses that we care about."""
+
+                fmris = self.pkgsend_bulk(self.dcs[1].get_repo_url(),
+                    self.sample_pkg)
+                self.depotconfig("")
+                self.start_depot()
+                # create an image so we have something to search with
+                # (bug 15807844) then retrieve the hash of a file we have
+                # published
+                self.image_create()
+                self.pkg("set-publisher -p %s/default" % self.ac.url)
+                ret, output = self.pkg("search -H -o action.hash "
+                     "-r /usr/bin/sample", out=True)
+                file_hash = output.strip()
+
+                fmri = pkg.fmri.PkgFmri(fmris[0])
+                esc_short_fmri = fmri.get_fmri(anarchy=True).replace(
+                    "pkg:/", "")
+                esc_short_fmri = esc_short_fmri.replace(",", "%2C")
+                esc_short_fmri = esc_short_fmri.replace(":", "%3A")
+
+                # a dictionary of paths we should be able to access, along with
+                # expected header (name,value) pairs for each
+                paths = {
+                    "/default/p5i/0/sample.p5i":
+                    [("Content-Type", "application/vnd.pkg5.info")],
+                    "/default/catalog/1/catalog.attrs":
+                    [("Cache-Control", "no-cache")],
+                    "/default/manifest/0/%s" % esc_short_fmri:
+                    [("Cache-Control",
+                    "must-revalidate, no-transform, max-age=31536000"),
+                    ("Content-Type", "text/plain;charset=utf-8")],
+                    "/default/search/1/False_2_None_None_%3a%3a%3asample":
+                    [("Cache-Control", "no-cache"),
+                    ("Content-Type", "text/plain;charset=utf-8")],
+                    "/default/file/1/%s" % file_hash:
+                    [("Cache-Control",
+                    "must-revalidate, no-transform, max-age=31536000"),
+                    ("Content-Type", "application/data")]
+                }
+
+                def header_contains(url, header, value):
+                        """Check that HTTP 'header' from 'url' contains an
+                        expected value 'value'."""
+                        ret = False
+                        try:
+                                u = urllib2.urlopen(url)
+                                h = u.headers.get(header, "")
+                                if value in h:
+                                        return True
+                        except Exception, e:
+                                self.assert_(False, "Error opening %s: %s" %
+                                    (url, e))
+                        return ret
+
+                for path in paths:
+                        for headers in paths[path]:
+                                name, value = headers
+                                url = "%s%s" % (self.ac.url, path)
+                                self.assert_(header_contains(url, name, value),
+                                    "%s did not contain the header %s=%s" %
+                                    (url, name, value))
+
+        def test_16_htfragment(self):
+                """Test that the fragment httpd.conf generated by pkg.depot-config
+                can be used in a standard Apache configuration, but that
+                pkg(1) admin and search operations fail."""
+
+                self.pkgsend_bulk(self.dcs[1].get_repo_url(),
+                    self.sample_pkg)
+                self.pkgrepo("-s %s add-publisher carrots" %
+                    self.dcs[1].get_repo_url())
+                self.pkgsend_bulk(self.dcs[1].get_repo_url(),
+                    self.carrots_pkg)
+                self.pkgsend_bulk(self.dcs[2].get_repo_url(),
+                    self.new_pkg)
+                self.depotconfig("-l %s -F -d usr=%s -d spaghetti=%s "
+                    "-P testpkg5" %
+                    (self.default_depot_runtime, self.rdir1, self.rdir2))
+                default_httpd_conf_path = os.path.join(self.test_root,
+                    "default_httpd.conf")
+                httpd_conf = open(default_httpd_conf_path, "w")
+                httpd_conf.write(self.__default_httpd_conf %
+                    {"port": self.depot_port,
+                    "depot_conf": self.depot_conf_fragment,
+                    "runtime_dir": self.default_depot_runtime})
+                httpd_conf.close()
+
+                # Start an Apache instance
+                ac = pkg5unittest.ApacheController(default_httpd_conf_path,
+                    self.depot_port, self.default_depot_runtime, testcase=self)
+                self.register_apache_controller("depot", ac)
+                ac.start()
+
+                # verify the instance is definitely the one using our custom
+                # httpd.conf
+                u = urllib2.urlopen("%s/pkg5test-server-status" % self.ac.url)
+                self.assert_(u.code == httplib.OK,
+                    "Error getting pkg5-server-status")
+
+                self.image_create()
+                # add publishers for the two repositories being served by this
+                # Apache instance
+                self.pkg("set-publisher -p %s/testpkg5/usr" % self.ac.url)
+                self.pkg("set-publisher -p %s/testpkg5/spaghetti" % self.ac.url)
+                # install packages from the two different publishers in the
+                # first repository
+                self.pkg("install sample")
+                self.pkg("install carrots")
+                # install a package from the second repository
+                self.pkg("install new")
+                # we can't perform remote search or admin operations, since
+                # we've no supporting mod_wsgi process.
+                self.pkg("search -r new", exit=1)
+                self.pkgrepo("-s %s/testpkg5/usr refresh" %
+                    self.ac.url, exit=1)
+
+        __svcs_template = \
+"""#!/usr/bin/ksh93
+#
+# This script produces false svcs(1) output, using
+# a list of space separated strings, with each string
+# of the format <fmri>%%<state>
+#
+# Since the string here is generated from a Python program, we have to escape
+# all 'percent' characters.
+#
+# eg.
+# SERVICE_STATUS="svc:/application/pkg/server:foo%%online svc:/application/pkg/server:default%%offline svc:/application/pkg/server:usr%%online"
+# We expect to be called with 'svcs -H -o fmri <fmri>' but completely ignore
+# the <fmri> argument.
+#
+SERVICE_STATUS="%s"
+
+set -- `getopt o:H $*`
+for i in $* ; do
+    case $i in
+        -H)    minus_h=$i; shift;;
+        -o)    minus_o=$2; shift;;
+        *)     break;;
+    esac
+done
+
+if [ "${minus_o}" ]; then
+    if [ -z "${minus_h}" ]; then
+        echo "FMRI"
+    fi
+    for service in $SERVICE_STATUS ; do
+        echo $service | sed -e 's/%%/ /' | read fmri state
+        echo $fmri
+    done
+    exit 0
+fi
+
+if [ -z "${minus_h}" ]; then
+    printf "%%-14s%%6s    %%s\n" STATE STIME FMRI
+fi
+for service in $SERVICE_STATUS ; do
+    echo $service | sed -e 's/%%/ /' | read fmri state
+    printf "%%-14s%%9s %%s\n" $state 00:00:00 $fmri
+done
+"""
+
+        __svcprop_template = \
+"""#!/usr/bin/ksh93
+#
+# This script produces false svcprop(1) output, using
+# a list of space separated strings, with each string
+# of the format <fmri>%%<state>%%<inst_root>%%<readonly>%%<standalone>
+#
+# eg.
+# SERVICE_PROPS="svc:/application/pkg/server:foo%%online%%/space/repo%%true%%false"
+#
+# we expect to be called as "svcprop -c -p <property> <fmri>"
+# which is enough svcprop(1) functionalty for these tests. Any other
+# command line options will cause us to return nonsense.
+#
+
+typeset -A prop_state
+typeset -A prop_readonly
+typeset -A prop_inst_root
+typeset -A prop_standalone
+
+SERVICE_PROPS="%s"
+for service in $SERVICE_PROPS ; do
+        echo $service | sed -e 's/%%/ /g' | \
+            read fmri state inst_root readonly standalone
+        # create a hashable version of the FMRI
+        fmri=$(echo $fmri | sed -e 's/\///g' -e 's/://g')
+        prop_state[$fmri]=$state
+        prop_inst_root[$fmri]=$inst_root
+        prop_readonly[$fmri]=$readonly
+        prop_standalone[$fmri]=$standalone
+done
+
+
+FMRI=$(echo $4 | sed -e 's/\///g' -e 's/://g')
+case $3 in
+        "pkg/inst_root")
+                echo ${prop_inst_root[$FMRI]}
+                ;;
+        "pkg/readonly")
+                echo ${prop_readonly[$FMRI]}
+                ;;
+        "pkg/standalone")
+                echo ${prop_standalone[$FMRI]}
+                ;;
+        "restarter/state")
+                echo ${prop_state[$FMRI]}
+                ;;
+        *)
+                echo "Completely bogus svcprop output. Sorry."
+esac
+"""
+
+        # A very minimal httpd.conf, which contains an Include directive
+        # that we will use to reference our pkg5 depot-config.conf file. We leave
+        # an Alias pointing to /server-status to make this server distinctive
+        # for this test case.
+        __default_httpd_conf = \
+"""ServerRoot "/usr/apache2/2.2"
+PidFile "%(runtime_dir)s/default_httpd.pid"
+Listen %(port)s
+<IfDefine 64bit>
+Include /etc/apache2/2.2/conf.d/modules-64.load
+</IfDefine>
+<IfDefine !64bit>
+Include /etc/apache2/2.2/conf.d/modules-32.load
+</IfDefine>
+
+User webservd
+Group webservd
+ServerAdmin [email protected]
+ServerName 127.0.0.1
+DocumentRoot "/var/apache2/2.2/htdocs"
+<Directory "/var/apache2/2.2/htdocs">
+    Options Indexes FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+<IfModule dir_module>
+    DirectoryIndex index.html
+</IfModule>
+LogFormat \"%%h %%l %%u %%t \\\"%%r\\\" %%>s %%b\" common
+ErrorLog "%(runtime_dir)s/error_log"
+CustomLog "%(runtime_dir)s/access_log" common
+LogLevel debug
+DefaultType text/plain
+# Reference the depot.conf file generated by pkg.depot-config, which makes this
+# web server into something that can serve pkg(5) repositories.
+Include %(depot_conf)s
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+# We enable server-status here, using /pkg5test-server-status to it to make the
+# URI distinctive.
+<Location /pkg5test-server-status>
+    SetHandler server-status
+</Location>
+"""
+
+if __name__ == "__main__":
+        unittest.main()
--- a/src/tests/cli/t_https.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_https.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 import sys
 
@@ -31,14 +31,16 @@
 import pkg5unittest
 
 import os
+import shutil
+import stat
 
+import pkg.misc as misc
 import pkg.portable as portable
 from pkg.client.debugvalues import DebugValues
 from pkg.client.transport.exception import TransportFailures
 
-class TestHTTPS(pkg5unittest.SingleDepotTestCase):
-        # Tests in this suite use the read only data directory.
-        need_ro_data = True
+
+class TestHTTPS(pkg5unittest.HTTPSTestClass):
 
         example_pkg10 = """
             open [email protected],5.11-0
@@ -47,116 +49,20 @@
 
         misc_files = ["tmp/example_file"]
 
-        def pkg(self, command, *args, **kwargs):
-                # The value for ssl_ca_file is pulled from DebugValues because
-                # ssl_ca_file needs to be set there so the api object calls work
-                # as desired.
-                command = "--debug ssl_ca_file=%s %s" % \
-                    (DebugValues["ssl_ca_file"], command)
-                return pkg5unittest.SingleDepotTestCase.pkg(self, command,
-                    *args, **kwargs)
-
-        def seed_ta_dir(self, certs, dest_dir=None):
-                if isinstance(certs, basestring):
-                        certs = [certs]
-                if not dest_dir:
-                        dest_dir = self.ta_dir
-                self.assert_(dest_dir)
-                self.assert_(self.raw_trust_anchor_dir)
-                for c in certs:
-                        name = "%s_cert.pem" % c
-                        portable.copyfile(
-                            os.path.join(self.raw_trust_anchor_dir, name),
-                            os.path.join(dest_dir, name))
-                        DebugValues["ssl_ca_file"] = os.path.join(dest_dir,
-                            name)
-
-        def killalldepots(self):
-                try:
-                        pkg5unittest.SingleDepotTestCase.killalldepots(self)
-                finally:
-                        if self.ac:
-                                self.debug("killing apache controller")
-                                try:
-                                        self.ac.kill()
-                                except Exception,e :
-                                        pass
-
         def setUp(self):
-                self.ac = None
-                pkg5unittest.SingleDepotTestCase.setUp(self, start_depot=True)
-                self.testdata_dir = os.path.join(self.test_root, "testdata")
-                self.make_misc_files(self.misc_files)
-
-                self.durl1 = self.dcs[1].get_depot_url()
-                self.rurl1 = self.dcs[1].get_repo_url()
+                pub1_name = "test"
+                pub2_name = "tmp"
 
-                # Set up the directories that apache needs.
-                self.apache_dir = os.path.join(self.test_root, "apache")
-                os.makedirs(self.apache_dir)
-                self.apache_log_dir = os.path.join(self.apache_dir,
-                    "apache_logs")
-                os.makedirs(self.apache_log_dir)
-                self.apache_content_dir = os.path.join(self.apache_dir,
-                    "apache_content")
-                self.pidfile = os.path.join(self.apache_dir, "httpd.pid")
-                self.common_config_dir = os.path.join(self.test_root,
-                    "apache-serve")
-
-                # Choose ports for apache to run on.
-                self.https_port = self.next_free_port
-                self.next_free_port += 1
-                self.proxy_port = self.next_free_port
-                self.next_free_port += 1
-                self.bad_proxy_port = self.next_free_port
-                self.next_free_port += 1
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub1_name, pub2_name],
+                    start_depots=True)
+                
+                self.rurl1 = self.dcs[1].get_repo_url()
+                self.rurl2 = self.dcs[2].get_repo_url()
+                self.tmppub = pub2_name
 
-                # Set up the paths to the certificates that will be needed.
-                self.path_to_certs = os.path.join(self.ro_data_root,
-                    "signing_certs", "produced")
-                self.keys_dir = os.path.join(self.path_to_certs, "keys")
-                self.cs_dir = os.path.join(self.path_to_certs,
-                    "code_signing_certs")
-                self.chain_certs_dir = os.path.join(self.path_to_certs,
-                    "chain_certs")
-                self.pub_cas_dir = os.path.join(self.path_to_certs,
-                    "publisher_cas")
-                self.inter_certs_dir = os.path.join(self.path_to_certs,
-                    "inter_certs")
-                self.raw_trust_anchor_dir = os.path.join(self.path_to_certs,
-                    "trust_anchors")
-                self.crl_dir = os.path.join(self.path_to_certs, "crl")
-
+                self.make_misc_files(self.misc_files)
                 self.pkgsend_bulk(self.rurl1, self.example_pkg10)
-
-                conf_dict = {
-                    "common_log_format": "%h %l %u %t \\\"%r\\\" %>s %b",
-                    "https_port": self.https_port,
-                    "proxy_port": self.proxy_port,
-                    "bad_proxy_port": self.bad_proxy_port,
-                    "log_locs": self.apache_log_dir,
-                    "pidfile": self.pidfile,
-                    "port": self.https_port,
-                    "proxied-server": self.durl1,
-                    "serve_root": self.apache_content_dir,
-                    "server-ssl-cert":os.path.join(self.cs_dir,
-                        "cs1_ta7_cert.pem"),
-                    "server-ssl-key":os.path.join(self.keys_dir,
-                        "cs1_ta7_key.pem"),
-                    "server-ca-cert":os.path.join(self.raw_trust_anchor_dir,
-                        "ta6_cert.pem"),
-                    "server-ca-taname": "ta6",
-                    "ssl-special": "%{SSL_CLIENT_I_DN_OU}",
-                }
-
-                self.https_conf_path = os.path.join(self.test_root,
-                    "https.conf")
-                with open(self.https_conf_path, "wb") as fh:
-                        fh.write(self.https_conf % conf_dict)
-                
-                self.ac = pkg5unittest.ApacheController(self.https_conf_path,
-                    self.https_port, self.common_config_dir, https=True)
-                self.acurl = self.ac.url
+                self.acurl = self.ac.url + "/%s" % pub1_name 
                 # Our proxy is served by the same Apache controller, but uses
                 # a different port.
                 self.proxyurl = self.ac.url.replace("https", "http")
@@ -179,18 +85,18 @@
                 # contain the trust anchor to verify the server's identity.
                 self.pkg("set-publisher -k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
-                }, exit=1)
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    }, exit=1)
 
                 # Add the trust anchor needed to verify the server's identity to
                 # the image.
                 self.seed_ta_dir("ta7")
                 self.pkg("set-publisher -k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
-                })
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    })
                 api_obj = self.get_img_api_obj()
                 self._api_install(api_obj, ["example_pkg"])
 
@@ -222,8 +128,8 @@
                 self.pkg("set-publisher --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": self.proxyurl})
                 self.pkg("install example_pkg")
 
@@ -237,8 +143,8 @@
                 self.pkg("set-publisher --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": bad_proxyurl}, exit=1)
 
                 # Set the bad proxy in the image, verify we can't refresh,
@@ -247,284 +153,187 @@
                 self.pkg("set-publisher --no-refresh --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -g %(url)s test" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": bad_proxyurl}, exit=0)
                 self.pkg("refresh", exit=1)
                 proxy_env = {"https_proxy": self.proxyurl}
                 self.pkg("refresh", env_arg=proxy_env)
                 self.pkg("install example_pkg", env_arg=proxy_env)
 
-
-        https_conf = """\
-# Configuration and logfile names: If the filenames you specify for many
-# of the server's control files begin with "/" (or "drive:/" for Win32), the
-# server will use that explicit path.  If the filenames do *not* begin
-# with "/", the value of ServerRoot is prepended -- so "/var/apache2/2.2/logs/foo_log"
-# with ServerRoot set to "/usr/apache2/2.2" will be interpreted by the
-# server as "/usr/apache2/2.2//var/apache2/2.2/logs/foo_log".
-
-#
-# ServerRoot: The top of the directory tree under which the server's
-# configuration, error, and log files are kept.
-#
-# Do not add a slash at the end of the directory path.  If you point
-# ServerRoot at a non-local disk, be sure to point the LockFile directive
-# at a local disk.  If you wish to share the same ServerRoot for multiple
-# httpd daemons, you will need to change at least LockFile and PidFile.
-#
-ServerRoot "/usr/apache2/2.2"
-
-PidFile "%(pidfile)s"
-
-#
-# Listen: Allows you to bind Apache to specific IP addresses and/or
-# ports, instead of the default. See also the <VirtualHost>
-# directive.
-#
-# Change this to Listen on specific IP addresses as shown below to 
-# prevent Apache from glomming onto all bound IP addresses.
-#
-Listen 0.0.0.0:%(https_port)s
-
-# We also make ourselves a general-purpose proxy. This is not needed for the
-# SSL reverse-proxying to the pkg.depotd, but allows us to test that pkg(1)
-# can communicate to HTTPS origins using a proxy.
-Listen 0.0.0.0:%(proxy_port)s
-Listen 0.0.0.0:%(bad_proxy_port)s
-
-#
-# Dynamic Shared Object (DSO) Support
-#
-# To be able to use the functionality of a module which was built as a DSO you
-# have to place corresponding `LoadModule' lines within the appropriate 
-# (32-bit or 64-bit module) /etc/apache2/2.2/conf.d/modules-*.load file so that
-# the directives contained in it are actually available _before_ they are used.
-#
-<IfDefine 64bit>
-Include /etc/apache2/2.2/conf.d/modules-64.load
-</IfDefine>
-<IfDefine !64bit>
-Include /etc/apache2/2.2/conf.d/modules-32.load
-</IfDefine>
-
-<IfModule !mpm_netware_module>
-#
-# If you wish httpd to run as a different user or group, you must run
-# httpd as root initially and it will switch.  
-#
-# User/Group: The name (or #number) of the user/group to run httpd as.
-# It is usually good practice to create a dedicated user and group for
-# running httpd, as with most system services.
-#
-User webservd
-Group webservd
-
-</IfModule>
+        def test_correct_cert_validation(self):
+                """ Test that an expired cert for one publisher doesn't prevent
+                making changes to other publishers due to certifcate checks on
+                all configured publishers. (Bug 17018362)"""
+                
+                bad_cert_path = os.path.join(self.cs_dir,
+                    "cs3_ch1_ta3_cert.pem")
+                good_cert_path = os.path.join(self.cs_dir,
+                    self.get_cli_cert("test"))
+                self.ac.start()
+                self.image_create()
+                
+                # Set https-based publisher with correct cert.
+                self.seed_ta_dir("ta7")
+                self.pkg("set-publisher -k %(key)s -c %(cert)s -p %(url)s" % {
+                    "url": self.acurl,
+                    "cert": good_cert_path,
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    })
+                # Set a second publisher
+                self.pkg("set-publisher -p %(url)s" % {"url": self.rurl2})
 
-# 'Main' server configuration
-#
-# The directives in this section set up the values used by the 'main'
-# server, which responds to any requests that aren't handled by a
-# <VirtualHost> definition.  These values also provide defaults for
-# any <VirtualHost> containers you may define later in the file.
-#
-# All of these directives may appear inside <VirtualHost> containers,
-# in which case these default settings will be overridden for the
-# virtual host being defined.
-#
-
-#
-# ServerName gives the name and port that the server uses to identify itself.
-# This can often be determined automatically, but we recommend you specify
-# it explicitly to prevent problems during startup.
-#
-# If your host doesn't have a registered DNS name, enter its IP address here.
-#
-ServerName 127.0.0.1
-
-#
-# DocumentRoot: The directory out of which you will serve your
-# documents. By default, all requests are taken from this directory, but
-# symbolic links and aliases may be used to point to other locations.
-#
-DocumentRoot "/"
-
-#
-# Each directory to which Apache has access can be configured with respect
-# to which services and features are allowed and/or disabled in that
-# directory (and its subdirectories). 
-#
-# First, we configure the "default" to be a very restrictive set of 
-# features.  
-#
-<Directory />
-    Options None
-    AllowOverride None
-    Order deny,allow
-    Deny from all
-</Directory>
+                # Replace cert of first publisher with one that is expired.
+                # It doesn't need to match the key because we just want to
+                # test if the cert validation code works correctly so we are not
+                # actually using the cert. 
 
-#
-# Note that from this point forward you must specifically allow
-# particular features to be enabled - so if something's not working as
-# you might expect, make sure that you have specifically enabled it
-# below.
-#
-
-#
-# This should be changed to whatever you set DocumentRoot to.
-#
-
-#
-# DirectoryIndex: sets the file that Apache will serve if a directory
-# is requested.
-#
-<IfModule dir_module>
-    DirectoryIndex index.html
-</IfModule>
+                # Cert is stored by content hash in the pkg config of the image.
+                ch = misc.get_data_digest(good_cert_path)[0]
+                pkg_cert_path = os.path.join(self.get_img_path(), "var", "pkg",
+                    "ssl", ch)
+                shutil.copy(bad_cert_path, pkg_cert_path)
 
-#
-# The following lines prevent .htaccess and .htpasswd files from being 
-# viewed by Web clients. 
-#
-<FilesMatch "^\.ht">
-    Order allow,deny
-    Deny from all
-    Satisfy All
-</FilesMatch>
-
-#
-# ErrorLog: The location of the error log file.
-# If you do not specify an ErrorLog directive within a <VirtualHost>
-# container, error messages relating to that virtual host will be
-# logged here.  If you *do* define an error logfile for a <VirtualHost>
-# container, that host's errors will be logged there and not here.
-#
-ErrorLog "%(log_locs)s/error_log"
-
-#
-# LogLevel: Control the number of messages logged to the error_log.
-# Possible values include: debug, info, notice, warn, error, crit,
-# alert, emerg.
-#
-LogLevel debug
+                # Refreshing the second publisher should not try to validate
+                # the cert for the first publisher.
+                self.pkg("refresh %s" % self.tmppub)
 
 
+class TestDepotHTTPS(pkg5unittest.SingleDepotTestCase):
+        # Tests in this suite use the read only data directory.
+        need_ro_data = True
 
-<IfModule log_config_module>
-    #
-    # The following directives define some format nicknames for use with
-    # a CustomLog directive (see below).
-    #
-    LogFormat "%(common_log_format)s" common
-    LogFormat "PROXY %(common_log_format)s" proxylog
+        example_pkg10 = """
+            open [email protected],5.11-0
+            add file tmp/example_file mode=0555 owner=root group=bin path=/usr/bin/example_path
+            close"""
 
-    #
-    # The location and format of the access logfile (Common Logfile Format).
-    # If you do not define any access logfiles within a <VirtualHost>
-    # container, they will be logged here.  Contrariwise, if you *do*
-    # define per-<VirtualHost> access logfiles, transactions will be
-    # logged therein and *not* in this file.
-    #
-    CustomLog "%(log_locs)s/access_log" common
-</IfModule>
+        misc_files = {
+            "tmp/example_file": "tmp/example_file",
+            "tmp/test_ssl_auth": """
+#!/usr/bin/sh
+reserved=$1
+port=$2
+echo "123"
+""",
+            "tmp/test_ssl_auth_bad": """
+#!/usr/bin/sh
+reserved=$1
+port=$2
+echo "12345"
+""",
+        }
 
-#
-# DefaultType: the default MIME type the server will use for a document
-# if it cannot otherwise determine one, such as from filename extensions.
-# If your server contains mostly text or HTML documents, "text/plain" is
-# a good value.  If most of your content is binary, such as applications
-# or images, you may want to use "application/octet-stream" instead to
-# keep browsers from trying to display binary files as though they are
-# text.
-#
-DefaultType text/plain
-
-<IfModule mime_module>
-    #
-    # TypesConfig points to the file containing the list of mappings from
-    # filename extension to MIME-type.
-    #
-    TypesConfig /etc/apache2/2.2/mime.types
+        def pkg(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "--debug ssl_ca_file=%s %s" % \
+                    (DebugValues["ssl_ca_file"], command)
+                return pkg5unittest.SingleDepotTestCase.pkg(self, command,
+                    *args, **kwargs)
 
-    #
-    # AddType allows you to add to or override the MIME configuration
-    # file specified in TypesConfig for specific file types.
-    #
-    AddType application/x-compress .Z
-    AddType application/x-gzip .gz .tgz
+        def seed_ta_dir(self, certs, dest_dir=None):
+                if isinstance(certs, basestring):
+                        certs = [certs]
+                if not dest_dir:
+                        dest_dir = self.ta_dir
+                for c in certs:
+                        name = "%s_cert.pem" % c
+                        portable.copyfile(
+                            os.path.join(self.raw_trust_anchor_dir, name),
+                            os.path.join(dest_dir, name))
+                        DebugValues["ssl_ca_file"] = os.path.join(dest_dir,
+                            name)
 
-    # Add a new mime.type for .p5i file extension so that clicking on
-    # this file type on a web page launches PackageManager in a Webinstall mode.
-    AddType application/vnd.pkg5.info .p5i
-</IfModule>
+        def setUp(self):
+                pkg5unittest.SingleDepotTestCase.setUp(self)
+                self.testdata_dir = os.path.join(self.test_root, "testdata")
+                mpaths = self.make_misc_files(self.misc_files)
+                self.ssl_auth_script = mpaths[1]
+                self.ssl_auth_bad_script = mpaths[2]
 
-#
-# Note: The following must must be present to support
-#       starting without SSL on platforms with no /dev/random equivalent
-#       but a statically compiled-in mod_ssl.
-#
-<IfModule ssl_module>
-SSLRandomSeed startup builtin
-SSLRandomSeed connect builtin
-</IfModule>
+                # Make shell scripts executable.
+                os.chmod(self.ssl_auth_script, stat.S_IRWXU)
+                os.chmod(self.ssl_auth_bad_script, stat.S_IRWXU)
 
-<VirtualHost 0.0.0.0:%(https_port)s>
-        AllowEncodedSlashes On
-        ProxyRequests Off
-        MaxKeepAliveRequests 10000
-
-        SSLEngine On
+                # Set up the paths to the certificates that will be needed.
+                self.path_to_certs = os.path.join(self.ro_data_root,
+                    "signing_certs", "produced")
+                self.keys_dir = os.path.join(self.path_to_certs, "keys")
+                self.cs_dir = os.path.join(self.path_to_certs,
+                    "code_signing_certs")
+                self.chain_certs_dir = os.path.join(self.path_to_certs,
+                    "chain_certs")
+                self.pub_cas_dir = os.path.join(self.path_to_certs,
+                    "publisher_cas")
+                self.inter_certs_dir = os.path.join(self.path_to_certs,
+                    "inter_certs")
+                self.raw_trust_anchor_dir = os.path.join(self.path_to_certs,
+                    "trust_anchors")
+                self.crl_dir = os.path.join(self.path_to_certs, "crl")
 
-        # Cert paths
-        SSLCertificateFile %(server-ssl-cert)s
-        SSLCertificateKeyFile %(server-ssl-key)s
-
-        # Combined product CA certs for client verification
-        SSLCACertificateFile %(server-ca-cert)s
+                self.pkgsend_bulk(self.rurl, self.example_pkg10)
 
-	SSLVerifyClient require
-
-        <Location />
-                SSLVerifyDepth 1
+                self.server_ssl_cert = os.path.join(self.cs_dir,
+                    "cs1_ta7_cert.pem")
+                self.server_ssl_key = os.path.join(self.keys_dir,
+                    "cs1_ta7_key.pem")
+                self.server_ssl_reqpass_key = os.path.join(self.keys_dir,
+                    "cs1_ta7_reqpass_key.pem")
 
-	        # The client's certificate must pass verification, and must have
-	        # a CN which matches this repository.
-                SSLRequire ( %(ssl-special)s =~ m/%(server-ca-taname)s/ )
+        def test_01_basics(self):
+                """Test that adding an https publisher works and that a package
+                can be installed from that publisher."""
 
-                # set max to number of threads in depot
-                ProxyPass %(proxied-server)s/ nocanon max=500
-        </Location>
-</VirtualHost>
+                def test_ssl_settings(exit=0):
+                        # Image must be created first before seeding cert files.
+                        self.pkg_image_create()
+                        self.seed_ta_dir("ta7")
+
+                        if exit != 0:
+                                self.dc.start_expected_fail(exit=exit)
+                                self.dc.disable_ssl()
+                                return
 
-#
-# We configure this Apache instance as a general-purpose HTTP proxy, accepting
-# requests from localhost, and allowing CONNECTs to our HTTPS port
-#
-<VirtualHost 0.0.0.0:%(proxy_port)s>
-        <Proxy *>
-                Order Deny,Allow
-                Deny from all
-                Allow from 127.0.0.1
-        </Proxy>
-        AllowCONNECT %(https_port)s
-        ProxyRequests on
-        CustomLog "%(log_locs)s/proxy_access_log" proxylog
-</VirtualHost>
+                        # Start depot *after* seeding certs.
+                        self.dc.start()
+
+                        self.pkg("set-publisher -p %s" % self.durl)
+                        api_obj = self.get_img_api_obj()
+                        self._api_install(api_obj, ["example_pkg"])
+
+                        self.dc.stop()
+                        self.dc.disable_ssl()
+
+                # Verify using 'builtin' ssl authentication for server with
+                # a key that has no passphrase.
+                self.dc.enable_ssl(key_path=self.server_ssl_key,
+                    cert_path=self.server_ssl_cert)
+                test_ssl_settings()
 
-<VirtualHost 0.0.0.0:%(bad_proxy_port)s>
-        <Proxy *>
-                Order Deny,Allow
-                Deny from all
-                Allow from 127.0.0.1
-        </Proxy>
-#  We purposely prevent this proxy from being able to connect to our SSL
-#  port, making sure that when we point pkg(1) to this bad proxy, operations
-#  will fail - the following line is commented out:
-#        AllowCONNECT %(https_port)s
-        ProxyRequests on
-        CustomLog "%(log_locs)s/badproxy_access_log" proxylog
+                # Verify using 'exec' ssl authentication for server with a key
+                # that has no passphrase.
+                self.dc.enable_ssl(key_path=self.server_ssl_key,
+                    cert_path=self.server_ssl_cert,
+                    dialog="exec:%s" % self.ssl_auth_script)
+                test_ssl_settings()
 
-</VirtualHost>
-"""
+                # Verify using 'exec' ssl authentication for server with a key
+                # that has a passphrase of '123'.
+                self.dc.enable_ssl(key_path=self.server_ssl_reqpass_key,
+                    cert_path=self.server_ssl_cert,
+                    dialog="exec:%s" % self.ssl_auth_script)
+                test_ssl_settings()
+
+                # Verify using 'exec' ssl authentication for server with a key
+                # that has a passphrase of 123' but the wrong passphrase is
+                # supplied.
+                self.dc.enable_ssl(key_path=self.server_ssl_reqpass_key,
+                    cert_path=self.server_ssl_cert,
+                    dialog="exec:%s" % self.ssl_auth_bad_script)
+                test_ssl_settings(exit=1)
+
+
+if __name__ == "__main__":
+        unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_origin_fw.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,148 @@
+#!/usr/bin/python
+# -*- coding: utf-8
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+
+import os
+import pkg5unittest
+import unittest
+
+import pkg.portable as portable
+
+class TestPkgFWDependencies(pkg5unittest.SingleDepotTestCase):
+        # Only start/stop the depot once (instead of for every test)
+        persistent_setup = True
+        # leverage smf test infrastructure here
+        smf_cmds = {
+            "testdriver" :
+"""#!/usr/bin/python
+import os
+import sys
+
+def main():
+    installed_version = os.environ.get("PKG_INSTALLED_VERSION", None)
+    devs_present = os.environ.get("PKG_NUM_FAKE_DEVICES", "1")
+    if not installed_version:
+        return 0
+    for arg in sys.argv[1:]:
+        if arg.startswith("minimum-version="):
+            c = cmp(installed_version, arg[len("minimum-version="):])
+            if c < 0:
+               if int(devs_present) > 240:
+                   devs_present = "240"
+               return int(devs_present)
+            return 0
+        if arg.startswith("dump_core="):
+            os.abort()
+    print "attribute minimum-version not specified in dependency"
+    return 241
+
+if __name__ == "__main__":
+        # Make all warnings be errors.
+        import warnings
+        warnings.simplefilter('error')
+        
+        sys.exit(main())
+"""}
+
+        def setUp(self):
+
+                pkg5unittest.SingleDepotTestCase.setUp(self)
+
+                self.pkg_list = []
+
+                for t in (
+                    ("1.0", "dwarf"),
+                    ("1.1", "elf"),
+                    ("1.2", "hobbit"),
+                    ("1.3", "wizard")
+                    ):
+                    self.pkg_list+= ["""
+                    open A@%s,5.11-0
+                    add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver minimum-version=%s 
+                    close 
+                    open B@%s,5.11-0
+                    add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver minimum-version=%s 
+                    close """ % (t + t) ]
+
+		self.pkg_list += ["""
+                    open [email protected],5.11-0
+                    add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver 
+                    close """]
+
+		self.pkg_list += ["""
+                    open [email protected],5.11-0
+                    add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver dump_core=1
+                    close"""]
+
+		self.pkg_list += ["""
+                    open [email protected],5.11-0
+                    add depend type=origin root-image=true fmri=pkg:/feature/firmware/no-such-enumerator
+                    close"""]
+
+        def test_fw_dependency(self):
+                """test origin firmware dependency"""
+		"""firmware test simulator uses alphabetic comparison"""
+
+		if portable.osname != "sunos":
+			raise pkg5unittest.TestSkippedException(
+			    "Firmware check unsupported on this platform.")
+
+                rurl = self.dc.get_repo_url()
+                plist = self.pkgsend_bulk(rurl, self.pkg_list)
+                self.image_create(rurl)
+
+                os.environ["PKG_INSTALLED_VERSION"] = "elf"
+		# trim some of the versions out; note that pkgs w/ firmware
+		# errors/problems are silently ignored.
+                self.pkg("install A B")
+		self.pkg("list")
+                self.pkg("verify [email protected]")
+		# test verify by changing device version
+		os.environ["PKG_INSTALLED_VERSION"] = "dwarf"
+		self.pkg("verify [email protected]", 1)
+                os.environ["PKG_INSTALLED_VERSION"] = "elf"
+		# exercise large number of devices code
+                os.environ["PKG_NUM_FAKE_DEVICES"] = "500"
+		self.pkg("install [email protected]", 1)
+		# exercise general error codes
+		self.pkg("install [email protected]", 1)
+		self.pkg("install [email protected]", 1)
+		# verify that upreving the firmware lets us install more
+                os.environ["PKG_INSTALLED_VERSION"] = "hobbit"
+		self.pkg("update")
+		self.pkg("verify [email protected]")
+		# simulate removing device
+		del os.environ["PKG_INSTALLED_VERSION"]
+		self.pkg("update")
+		self.pkg("list")
+		self.pkg("verify [email protected]") 
+		# ok since we never drop core 
+		# here as device 
+		# doesn't exist.
+		
+		# check that we ignore dependencies w/ missing enumerators for now
+		self.pkg("install [email protected]")
+
--- a/src/tests/cli/t_pkg_composite.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_composite.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,8 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+
 
 import testutils
 if __name__ == "__main__":
@@ -177,7 +178,7 @@
 
         def setUp(self):
                 pkg5unittest.ManyDepotTestCase.setUp(self, ["test", "test",
-                    "test", "empty"])
+                    "test", "empty", "void"])
                 self.make_misc_files(self.misc_files)
 
                 # First repository will contain all packages.
@@ -193,6 +194,10 @@
                 self.empty_rurl = self.dcs[4].get_repo_url()
                 self.pkgrepo("refresh -s %s" % self.empty_rurl)
 
+                # Fifth will have a publisher named 'void', but no packages.
+                self.void_rurl = self.dcs[5].get_repo_url()
+                self.pkgrepo("refresh -s %s" % self.void_rurl)
+
                 # Setup base test paths.
                 self.path_to_certs = os.path.join(self.ro_data_root,
                     "signing_certs", "produced")
@@ -322,6 +327,10 @@
                 """Verify that the info operation works as expected when
                 compositing publishers.
                 """
+		# because we compare date strings we must run this in
+		# a consistent locale, which we made 'C'
+
+		os.environ['LC_ALL'] = 'C'
 
                 # Create an image and verify no packages are known.
                 self.image_create(self.empty_rurl, prefix=None)
@@ -548,6 +557,25 @@
                 output = output[:output.find("pkg: ")] + "\n"
                 self.assertEqualDiff(expected, output)
 
+        def test_05_empty(self):
+                """Verify empty repositories and repositories with a publisher,
+                but no packages, can be used with -g."""
+
+                self.image_create(repourl=None, prefix=None)
+
+                # Verify usage alone.
+                for uri in (self.empty_rurl, self.void_rurl):
+                        self.pkg("list -afH -g %s '*'" % uri, exit=1)
+                        self.pkg("contents -H -g %s '*'" % uri, exit=1)
+
+                # Verify usage in combination with non-empty.
+                self.pkg("list -afH -g %s -g %s -g %s '*'" % (self.empty_rurl,
+                    self.void_rurl, self.foo_rurl))
+                expected = \
+                    ("foo (test) 1.0 ---\n")
+                output = self.reduceSpaces(self.output)
+                self.assertEqualDiff(expected, output)
+
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_depotd.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_depotd.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -86,6 +86,11 @@
             add depend type=require fmri=pkg:/SUNWcsl
             close """
 
+        entire10 = """
+            open [email protected],5.11-0
+            add depend type=incorporate fmri=pkg:/foo
+            close """
+
         misc_files = [ "tmp/libc.so.1", "tmp/cat" ]
 
         def setUp(self):
@@ -371,6 +376,21 @@
                 self.dc.set_repodir(lsrc)
                 self.dc.start()
 
+        def test_empty_incorp_depend(self):
+                """ Bug 16304629
+                Test that a version-less incorporate dependency in a package
+                doesn't cause a traceback and a 404 in the BUI.
+                """
+                depot_url = self.dc.get_depot_url()
+                self.pkgsend_bulk(depot_url, self.foo10)
+                self.pkgsend_bulk(depot_url, self.entire10)
+
+                repourl = urlparse.urljoin(depot_url,
+                    "/en/catalog.shtml?version=%s&action=Browse" %
+                    urllib.quote("[email protected],5.11-0"))
+
+                res = urllib2.urlopen(repourl)
+
 
 class TestDepotController(pkg5unittest.CliTestCase):
 
--- a/src/tests/cli/t_pkg_image_create.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_image_create.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -225,7 +225,7 @@
                 information work as expected for image-create."""
 
                 img_path = os.path.join(self.test_root, "test_4_img")
-                for opt in ("-a", "-p", "--publisher"):
+                for opt in ("-p", "--publisher"):
                         self.pkg("image-create %s test1=%s %s" % (opt,
                             self.rurl1, img_path))
                         shutil.rmtree(img_path)
@@ -252,6 +252,17 @@
                             img_path, u))
                 shutil.rmtree(img_path, True)
 
+                # Verify that specifying --no-refresh when use-system-repo
+                # is set to true works.
+                saved_sysrepo_env = os.environ.get("PKG_SYSREPO_URL")
+                os.environ["PKG_SYSREPO_URL"] = "http://localhost:1"
+                self.pkg("image-create --no-refresh --set-property \
+                    use-system-repo=true %s" % img_path)
+                shutil.rmtree(img_path)
+                if saved_sysrepo_env:
+                        os.environ["PKG_SYSREPO_URL"] = saved_sysrepo_env
+
+
                 # Verify that simple paths to file repositories can be used
                 # (not just file:// URIs).
                 mirrors = " ".join(
@@ -782,6 +793,9 @@
                     self.pkg, "image-create -p test1=ftp://%s1" %
                     self.bogus_url)
 
+                self.assertRaises(pkg5unittest.UnexpectedExitCodeException, \
+                    self.pkg, "image-create -p test1=ftp://%s1 -p test2=http://%s2:abc" %
+                    (self.bogus_url, self.bogus_url))
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_info.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_info.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -79,6 +79,15 @@
             "tmp/bronze2", "tmp/copyright1", "tmp/copyright0", "tmp/sh",
             "tmp/baz"]
 
+        def __check_qoutput(self, errout=False):
+                self.assertEqualDiff(self.output, "")
+                if errout:
+                        self.assert_(self.errout != "",
+                            "-q must print fatal errors!")
+                else:
+                        self.assert_(self.errout == "",
+                            "-q should only print fatal errors!")
+
         def setUp(self):
                 pkg5unittest.SingleDepotTestCase.setUp(self)
                 self.make_misc_files(self.misc_files)
@@ -97,6 +106,9 @@
                 self.image_create(self.rurl)
 
                 self.pkg("info [email protected]", exit=1)
+                # Should only print fatal errors when using -q.
+                self.pkg("info -q [email protected]", exit=1)
+                self.__check_qoutput(errout=True)
                 self.pkg("info pkg:/[email protected],5.11-0.95:20080807T160129",
                     exit=1)
                 self.pkg("info pkg:/[email protected],5.11-0.95:20080807T1", exit=1)
@@ -174,6 +186,9 @@
                 self.pkg("info 'j*'")
                 self.pkg("info '*a*'")
                 self.pkg("info jade", su_wrap=True)
+                # Should only print fatal errors when using -q.
+                self.pkg("info -q jade")
+                self.__check_qoutput(errout=False)
 
                 # Check remote info
                 self.pkg("info -r jade | grep 'State: Installed'")
@@ -183,6 +198,9 @@
                 self.pkg("info -r turquoise | grep '      Category: System/Security/Foo/bar/Baz'")
                 self.pkg("info -r turquoise | grep '      Category: System/Security/Foo/bar/Baz (org.opensolaris.category.2008)'", exit=1)
                 self.pkg("info -r turquoise | grep '   Description: Short desc'")
+                # Should only print fatal errors when using -q.
+                self.pkg("info -qr turquoise")
+                self.__check_qoutput(errout=False)
                 self.pkg("info -r turquoise")
 
                 # Now remove the manifest for turquoise and retry the info -r
@@ -207,8 +225,16 @@
                 self.assertEqual(lines[4], "                depend on the presence of this incorporation.  Removing this")
                 self.assertEqual(lines[5], "                package will result in an unsupported system.")
                 self.assertEqual(lines[6], "         State: Not installed")
+                # Should only print fatal errors when using -q.
+                self.pkg("info -qr turquoise")
+                self.__check_qoutput(errout=False)
+                # Now check for an unknown remote package.
                 self.pkg("info -r emerald", exit=1)
                 self.pkg("info -r emerald 2>&1 | grep 'no packages matching'")
+                # Should only print fatal errors when using -q.
+                self.pkg("info -qr emerald", exit=1)
+                self.__check_qoutput(errout=False)
+
                 self.dc.stop()
 
         def test_bug_2274(self):
@@ -227,15 +253,29 @@
                 self.image_create(self.rurl)
                 self.pkg("info --license -r bronze")
                 self.pkg("info --license -r silver", exit=1)
+                # Should only print fatal errors when using -q.
+                self.pkg("info --license -qr silver", exit=1)
+                self.__check_qoutput(errout=False)
                 self.pkg("info --license -r bronze silver", exit=3)
                 self.pkg("info --license -r silver 2>&1 | grep 'no license information'")
 
-                self.pkg("install bronze")
-                self.pkg("install silver")
+                self.pkg("install bronze silver")
 
                 self.pkg("info --license bronze")
+                # Should only print fatal errors when using -q.
+                self.pkg("info --license -q bronze")
+                self.__check_qoutput(errout=False)
+
                 self.pkg("info --license silver", exit=1)
+                # Should only print fatal errors when using -q.
+                self.pkg("info --license -q silver", exit=1)
+                self.__check_qoutput(errout=False)
+
                 self.pkg("info --license bronze silver", exit=3)
+                # Should only print fatal errors when using -q.
+                self.pkg("info --license -q bronze silver", exit=3)
+                self.__check_qoutput(errout=False)
+
                 self.pkg("info --license silver 2>&1 | grep 'no license information'")
 
         def test_info_bad_packages(self):
@@ -283,6 +323,11 @@
                 multiple publishers provide the same package based on
                 publisher search order."""
 
+		# because we compare date strings we must run this in
+		# a consistent locale, which we made 'C'
+
+		os.environ['LC_ALL'] = 'C'
+
                 # Create an isolated repository for this test
                 repodir = os.path.join(self.test_root, "test-ranked")
                 self.create_repo(repodir)
@@ -433,6 +478,11 @@
                 """Verify that info returns the expected output for renamed
                 packages."""
 
+		# because we compare date strings we must run this in
+		# a consistent locale, which we made 'C'
+
+		os.environ['LC_ALL'] = 'C'
+
                 target10 = """
                     open [email protected]
                     close
--- a/src/tests/cli/t_pkg_install.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_install.py	Wed Aug 14 11:12:35 2013 +0530
@@ -659,7 +659,7 @@
                                     "'%s'." % bad_mode)
                                 bad_mdata = mdata.replace(src_mode, bad_mode)
                                 self.write_img_manifest(pfmri, bad_mdata)
-                                self.pkg("--debug skip-verify-manifest=True "
+                                self.pkg("--debug manifest_validate=Never "
                                     "install %s" % pfmri.pkg_name, exit=1)
 
                         # Now attempt to corrupt the client's copy of the
@@ -672,7 +672,7 @@
                                 bad_mdata = mdata.replace("owner=root",
                                     bad_owner)
                                 self.write_img_manifest(pfmri, bad_mdata)
-                                self.pkg("--debug skip-verify-manifest=True "
+                                self.pkg("--debug manifest_validate=Never "
                                     "install %s" % pfmri.pkg_name, exit=1)
 
                         for bad_group in ("", 'group=""', "group=invalidgroup"):
@@ -682,7 +682,7 @@
                                 bad_mdata = mdata.replace("group=bin",
                                     bad_group)
                                 self.write_img_manifest(pfmri, bad_mdata)
-                                self.pkg("--debug skip-verify-manifest=True "
+                                self.pkg("--debug manifest_validate=Never "
                                     "install %s" % pfmri.pkg_name, exit=1)
 
                         # Now attempt to corrupt the client's copy of the
@@ -694,7 +694,7 @@
                                     "'%s'." % bad_act)
                                 bad_mdata = mdata + "%s\n" % bad_act
                                 self.write_img_manifest(pfmri, bad_mdata)
-                                self.pkg("--debug skip-verify-manifest=True "
+                                self.pkg("--debug manifest_validate=Never "
                                     "install %s" % pfmri.pkg_name, exit=1)
 
         def test_bug_3770(self):
@@ -777,23 +777,48 @@
                 ):
                         self.debug("fname: %s" % name)
                         self.assert_(os.path.exists(os.path.join(self.get_img_path(),
-name)))
+                            name)))
 
                 self.pkg("uninstall -vvv fuzzy")
 
+
+class TestPkgInstallApache(pkg5unittest.ApacheDepotTestCase):
+
+        # Only start/stop the depot once (instead of for every test)
+        persistent_setup = True
+
+        foo11 = """
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/lib
+            add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1 timestamp="20080731T024051Z"
+            close """
+
+        upgrade_np10 = """
+            open [email protected],5.11-0
+            close"""
+
+        misc_files = [ "tmp/libc.so.1" ]
+
+        def setUp(self):
+                pkg5unittest.ApacheDepotTestCase.setUp(self, ["test1", "test2"],
+                    start_depots=True)
+                self.make_misc_files(self.misc_files)
+                self.durl1 = self.dcs[1].get_depot_url()
+                self.durl2 = self.dcs[2].get_depot_url()
+                self.pkgsend_bulk(self.durl1, self.foo11)
+                self.pkgsend_bulk(self.durl2, self.upgrade_np10)
+
         def test_corrupt_web_cache(self):
                 """Make sure the client can detect corrupt content being served
                 to it from a corrupt web cache, modifying its requests to
                 retrieve correct content."""
 
-                # Depot required for this test since we want to corrupt
-                # a downstream cache serving this content
-                self.dc.start()
-                fmris = self.pkgsend_bulk(self.durl, self.foo11)
+                fmris = self.pkgsend_bulk(self.durl1, (self.foo11,
+                    self.upgrade_np10))
                 # we need to record just the version string of foo in order
                 # to properly quote it later.
                 foo_version = fmris[0].split("@")[1]
-                self.image_create(self.durl)
+                self.image_create(self.durl1)
 
                 # we use the system repository as a convenient way to setup
                 # a caching proxy
@@ -809,6 +834,7 @@
                 self.next_free_port += 1
                 sc = pkg5unittest.SysrepoController(sc_conf,
                     sysrepo_port, sc_runtime_dir, testcase=self)
+                self.register_apache_controller("sysrepo", sc)
                 sc.start()
 
                 sysrepo_url = "http://localhost:%s" % sysrepo_port
@@ -854,10 +880,10 @@
                     # format pkg(1) uses - two logically identical urls that
                     # differ only by the way they're quoted are treated by
                     # Apache as separate cacheable resources.
-                    "%s/test/manifest/0/foo@%s" % (self.durl, urllib2.quote(
+                    "%s/test1/manifest/0/foo@%s" % (self.durl1, urllib2.quote(
                     foo_version)),
-                    "%s/test/file/1/8535c15c49cbe1e7cb1a0bf8ff87e512abed66f8" %
-                    self.durl,
+                    "%s/test1/file/1/8535c15c49cbe1e7cb1a0bf8ff87e512abed66f8" %
+                    self.durl1,
                 ]
 
                 proxy_handler = urllib2.ProxyHandler({"http": sysrepo_url})
@@ -900,9 +926,9 @@
                 # ensure that when we actually corrupt the repository
                 # as well as the cache, we do detect the errors properly.
                 corrupt_cache(sc_cache)
-                repodir = self.dc.get_repodir()
-
-                prefix = "publisher/test"
+                repodir = self.dcs[1].get_repodir()
+
+                prefix = "publisher/test1"
                 self.image_create(props={"use-system-repo": True})
 
                 # When we corrupt the files in the repository, we intentionally
@@ -943,7 +969,7 @@
                         corrupt_cache(sc_cache)
                         corrupt_path(mfpath, value="spaghetti\n", rename=True)
                         shutil.rmtree(os.path.join(self.img_path(),
-                            "var/pkg/publisher/test/pkg"))
+                            "var/pkg/publisher/test1/pkg"))
                         self.pkg("contents -rm [email protected]", stderr=True, exit=1)
                         os.rename(mfpath + ".not-corrupt", mfpath)
                 
@@ -971,11 +997,87 @@
                                 if os.path.exists(not_corrupt):
                                         os.rename(not_corrupt, path)
 
-                        sc.stop()
                         if saved_pkg_sysrepo_env:
                                 os.environ["PKG_SYSREPO_URL"] = \
                                     saved_pkg_sysrepo_env
 
+        def test_granular_proxy(self):
+                """Tests that images can use the set-publisher --proxy argument
+                to selectively proxy requests."""
+
+                # we use the system repository as a convenient way to setup
+                # a caching proxy.   Since the image doesn't have the property
+                # 'use-system-repo=True', the configuration of the sysrepo
+                # will remain static.
+                self.image_create(self.durl1)
+                self.sysrepo("")
+                sc_runtime_dir = os.path.join(self.test_root, "sysrepo_runtime")
+                sc_conf = os.path.join(sc_runtime_dir, "sysrepo_httpd.conf")
+                sc_cache = os.path.join(self.test_root, "sysrepo_cache")
+
+                # ensure pkg5srv can write cache content
+                os.chmod(sc_cache, 0777)
+
+                sysrepo_port = self.next_free_port
+                self.next_free_port += 1
+                sc = pkg5unittest.SysrepoController(sc_conf,
+                    sysrepo_port, sc_runtime_dir, testcase=self)
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
+                sysrepo_url = "http://localhost:%s" % sysrepo_port
+
+                self.image_create()
+                self.pkg("set-publisher -p %s --proxy %s" % (self.durl1,
+                    sysrepo_url))
+                self.pkg("install foo")
+                self.pkg("uninstall foo")
+
+                sc.stop()
+                # with our proxy offline, and with no other origins
+                # available, we should be unable to install
+                self.pkg("install --no-refresh foo", exit=1)
+                sc.start()
+
+                # we cannot add another origin with the same url
+                self.pkg("set-publisher --no-refresh -g %s test1" %
+                    self.durl1, exit=1)
+                # we cannot add another proxied origin with that url
+                self.pkg("set-publisher --no-refresh -g %s "
+                    "--proxy http://noodles test1" % self.durl1,
+                    exit=1)
+
+                # Now add a second, unproxied publisher, ensuring we
+                # can install packages from there.  Since the proxy
+                # isn't configured to proxy that resource, this tests
+                # that the proxy for self.durl1 isn't being used.
+                self.pkg("set-publisher -g %s test2" % self.durl2)
+                self.pkg("install --no-refresh "
+                    "pkg://test2/[email protected]")
+                self.pkg("uninstall pkg://test2/[email protected]")
+                self.pkg("set-publisher -G %s test2" % self.durl2)
+
+                # check that runtime proxies are being used - we
+                # set a bogus proxy, then ensure our $http_proxy value
+                # gets used.
+                self.pkg("publisher")
+                self.pkg("set-publisher -G %s test1" % self.durl1)
+                self.pkg("set-publisher --no-refresh -g %s "
+                    "--proxy http://noodles test1" % self.durl1)
+                env = {"http_proxy": sysrepo_url}
+                self.pkg("refresh", env_arg=env)
+                self.pkg("install foo", env_arg=env)
+                self.pkg("uninstall foo", env_arg=env)
+
+                # check that $all_proxy works
+                env = {"all_proxy": sysrepo_url}
+                self.pkg("install foo", env_arg=env)
+                self.pkg("uninstall foo", env_arg=env)
+
+                # now check that no_proxy works
+                env["no_proxy"] = "*"
+                self.pkg("install foo", env_arg=env)
+                self.pkg("refresh --full", env_arg=env)
+
 
 class TestPkgInstallRepoPerTest(pkg5unittest.SingleDepotTestCase):
         persistent_setup = False
@@ -2009,17 +2111,37 @@
             close
         """
 
+        linkpreserve = """
+            open [email protected]
+            add file tmp/preserve1 path=etc/ssh/sshd_config mode=0644 owner=root group=root preserve=true
+            close
+            open [email protected]
+            add file tmp/preserve2 path=etc/sunssh/sshd_config mode=0644 owner=root group=root preserve=true original_name=linkpreserve:etc/ssh/sshd_config
+            add link path=etc/ssh/sshd_config target=../sunssh/sshd_config
+            close """
+
         salvage = """
             open [email protected]
             add dir path=var mode=755 owner=root group=root
             add dir path=var/mail mode=755 owner=root group=root
             add dir path=var/log mode=755 owner=root group=root
+            add dir path=var/noodles mode=755 owner=root group=root
+            add dir path=var/persistent mode=755 owner=root group=root
             close
             open [email protected]
             add dir path=var mode=755 owner=root group=root
             add dir path=var/.migrate-to-shared mode=755 owner=root group=root
             add dir path=var/.migrate-to-shared/mail salvage-from=var/mail mode=755 owner=root group=root
             add dir path=var/.migrate-to-shared/log salvage-from=var/log mode=755 owner=root group=root
+            add dir path=var/spaghetti mode=755 owner=root group=root
+            add dir path=var/persistent mode=755 owner=root group=root salvage-from=var/noodles
+            close
+            open [email protected]
+            add dir path=var mode=755 owner=root group=root
+            add dir path=var/.migrate-to-shared mode=755 owner=root group=root
+            add dir path=var/.migrate-to-shared/mail salvage-from=var/mail mode=755 owner=root group=root
+            add dir path=var/.migrate-to-shared/log salvage-from=var/log mode=755 owner=root group=root
+            add dir path=var/persistent mode=755 owner=root group=root salvage-from=var/noodles salvage-from=var/spaghetti
             close
         """
 
@@ -2819,7 +2941,7 @@
                 self.file_contains("newme", "preserve2")
 
         def test_directory_salvage(self):
-                """Make sure directory salvage works as expected"""
+                """Make sure basic directory salvage works as expected"""
                 self.pkgsend_bulk(self.rurl, self.salvage)
                 self.image_create(self.rurl)
                 self.pkg("install [email protected]")
@@ -2831,6 +2953,33 @@
                 self.file_exists("var/.migrate-to-shared/mail/bar")
                 self.file_exists("var/.migrate-to-shared/mail/baz")
 
+        def test_directory_salvage_persistent(self):
+                """Make sure directory salvage works as expected when salvaging
+                content to an existing packaged directory."""
+
+                # we salvage content from two directories,
+                # var/noodles and var/spaghetti each of which disappear over
+                # subsequent updates.
+                self.pkgsend_bulk(self.rurl, self.salvage)
+                self.image_create(self.rurl)
+                self.pkg("install [email protected]")
+                self.file_append("var/mail/foo", "foo's mail")
+                self.file_append("var/noodles/noodles.txt", "yum")
+                self.pkg("update [email protected]")
+                self.file_exists("var/.migrate-to-shared/mail/foo")
+                self.file_exists("var/persistent/noodles.txt")
+                self.file_append("var/spaghetti/spaghetti.txt", "yum")
+                self.pkg("update")
+                self.file_exists("var/persistent/noodles.txt")
+                self.file_exists("var/persistent/spaghetti.txt")
+
+                # ensure that we can jump from 1.0 to 3.0 directly.
+                self.image_create(self.rurl)
+                self.pkg("install [email protected]")
+                self.file_append("var/noodles/noodles.txt", "yum")
+                self.pkg("update  [email protected]")
+                self.file_exists("var/persistent/noodles.txt")
+
         def test_special_salvage(self):
                 """Make sure salvaging directories with special files works as
                 expected."""
@@ -2877,6 +3026,42 @@
                                         continue
                                 self.validate_fsobj_attrs(a, target=dest)
 
+        def test_link_preserve(self):
+                """Ensure that files transitioning to a link still follow
+                original_name preservation rules."""
+
+                self.pkgsend_bulk(self.rurl, (self.linkpreserve))
+                self.image_create(self.rurl, destroy=True, fs=("var",))
+
+                # Install package with original config file location.
+                self.pkg("install [email protected]")
+                cfg_path = os.path.join("etc", "ssh", "sshd_config")
+                abs_path = os.path.join(self.get_img_path(), cfg_path)
+
+                self.file_exists(cfg_path)
+                self.assert_(not os.path.islink(abs_path))
+
+                # Modify the file.
+                self.file_append(cfg_path, "modified")
+
+                # Install new package version, verify file replaced with link
+                # and modified version was moved to new location.
+                new_cfg_path = os.path.join("etc", "sunssh", "sshd_config")
+                self.pkg("update [email protected]")
+                self.assert_(os.path.islink(abs_path))
+                self.file_exists(new_cfg_path)
+                self.file_contains(new_cfg_path, "modified")
+
+                # Uninstall, then install original version again.
+                self.pkg("uninstall linkpreserve")
+                self.pkg("install [email protected]")
+                self.file_contains(cfg_path, "preserve1")
+
+                # Install new package version and verify that unmodified file is
+                # replaced with new configuration file.
+                self.pkg("update [email protected]")
+                self.file_contains(new_cfg_path, "preserve2")
+
 
 class TestPkgInstallActions(pkg5unittest.SingleDepotTestCase):
         # Only start/stop the depot once (instead of for every test)
@@ -5249,91 +5434,6 @@
                 # Check if install -n returns with exit code 1
                 self.pkg("install -n moo", exit=1)
 
-        def test_20_granular_proxy(self):
-                """Tests that images can use the set-publisher --proxy argument
-                to selectively proxy requests."""
-
-                self.dcs[1].start()
-                self.dcs[2].start()
-                # we use the system repository as a convenient way to setup
-                # a caching proxy.   Since the image doesn't have the property
-                # 'use-system-repo=True', the configuration of the sysrepo
-                # will remain static.
-                self.image_create(self.durl1)
-                self.sysrepo("")
-                sc_runtime_dir = os.path.join(self.test_root, "sysrepo_runtime")
-                sc_conf = os.path.join(sc_runtime_dir, "sysrepo_httpd.conf")
-                sc_cache = os.path.join(self.test_root, "sysrepo_cache")
-
-                # ensure pkg5srv can write cache content
-                os.chmod(sc_cache, 0777)
-
-                sysrepo_port = self.next_free_port
-                self.next_free_port += 1
-                sc = pkg5unittest.SysrepoController(sc_conf,
-                    sysrepo_port, sc_runtime_dir, testcase=self)
-
-                try:
-                        sc.start()
-                        sysrepo_url = "http://localhost:%s" % sysrepo_port
-
-                        self.image_create()
-                        self.pkg("set-publisher -p %s --proxy %s" % (self.durl1,
-                            sysrepo_url))
-                        self.pkg("install foo")
-                        self.pkg("uninstall foo")
-
-                        sc.stop()
-                        # with our proxy offline, and with no other origins
-                        # available, we should be unable to install
-                        self.pkg("install --no-refresh foo", exit=1)
-                        sc.start()
-
-                        # we cannot add another origin with the same url
-                        self.pkg("set-publisher --no-refresh -g %s test1" %
-                            self.durl1, exit=1)
-                        # we cannot add another proxied origin with that url
-                        self.pkg("set-publisher --no-refresh -g %s "
-                            "--proxy http://noodles test1" % self.durl1,
-                            exit=1)
-
-                        # Now add a second, unproxied publisher, ensuring we
-                        # can install packages from there.  Since the proxy
-                        # isn't configured to proxy that resource, this tests
-                        # that the proxy for self.durl1 isn't being used.
-                        self.pkg("set-publisher -g %s test2" % self.durl2)
-                        self.pkg("install --no-refresh "
-                            "pkg://test2/[email protected]")
-                        self.pkg("uninstall pkg://test2/[email protected]")
-                        self.pkg("set-publisher -G %s test2" % self.durl2)
-
-                        # check that runtime proxies are being used - we
-                        # set a bogus proxy, then ensure our $http_proxy value
-                        # gets used.
-                        self.pkg("publisher")
-                        self.pkg("set-publisher -G %s test1" % self.durl1)
-                        self.pkg("set-publisher --no-refresh -g %s "
-                            "--proxy http://noodles test1" % self.durl1)
-                        env = {"http_proxy": sysrepo_url}
-                        self.pkg("refresh", env_arg=env)
-                        self.pkg("install foo", env_arg=env)
-                        self.pkg("uninstall foo", env_arg=env)
-
-                        # check that $all_proxy works
-                        env = {"all_proxy": sysrepo_url}
-                        self.pkg("install foo", env_arg=env)
-                        self.pkg("uninstall foo", env_arg=env)
-
-                        # now check that no_proxy works
-                        env["no_proxy"] = "*"
-                        self.pkg("install foo", env_arg=env)
-                        self.pkg("refresh --full", env_arg=env)
-
-                finally:
-                        if sc.is_alive():
-                                sc.stop()
-                        self.killalldepots()
-
 
 class TestImageCreateCorruptImage(pkg5unittest.SingleDepotTestCaseCorruptImage):
         """
@@ -6818,6 +6918,10 @@
         actions into the same name in a namespace cannot be installed
         simultaneously."""
 
+        pkg_boring10 = """
+            open [email protected],5.11-0
+            close """
+
         pkg_dupfiles = """
             open dupfiles@0,5.11-0
             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
@@ -6886,8 +6990,39 @@
 
         pkg_overlaid = """
             open overlaid@0,5.11-0
+            add dir path=etc mode=0755 owner=root group=root
             add file tmp/file1 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=allow
             close
+            open overlaid@1,5.11-0
+            add dir path=etc mode=0755 owner=root group=root
+            add file tmp/file1 path=etc/pam.conf mode=644 owner=root group=sys preserve=renamenew overlay=allow
+            close
+            open overlaid@2,5.11-0
+            add dir path=etc mode=0755 owner=root group=root
+            add file tmp/file3 path=etc/pam.conf mode=644 owner=root group=sys preserve=renamenew overlay=allow
+            close
+            open overlaid@3,5.11-0
+            add set name=pkg.renamed value=true
+            add depend type=require fmri=overlaid-renamed@3
+            add depend type=exclude fmri=overlaid-renamed@4
+            close
+            open overlaid-renamed@3,5.11-0
+            add depend type=optional fmri=overlaid@3
+            add dir path=etc mode=0755 owner=root group=root
+            add file tmp/file3 original_name=overlaid:etc/pam.conf path=etc/pam.conf mode=644 owner=root group=sys preserve=renamenew overlay=allow
+            close
+            open [email protected],5.11-0
+            add depend type=optional fmri=overlaid@3
+            add dir path=etc mode=0755 owner=root group=root
+            add dir path=etc/pam mode=0755 owner=root group=root
+            add file tmp/file4 original_name=overlaid:etc/pam.conf path=etc/pam/pam.conf mode=644 owner=root group=sys preserve=renamenew
+            close
+            open [email protected],5.11-0
+            add depend type=optional fmri=overlaid@3
+            add dir path=etc mode=0755 owner=root group=root
+            add dir path=etc/pam mode=0755 owner=root group=root
+            add file tmp/file4 original_name=overlaid:etc/pam.conf path=etc/pam/pam.conf mode=644 owner=root group=sys preserve=renamenew overlay=allow
+            close
         """
 
         # 'overlay' is ignored unless 'preserve' is also set.
@@ -6903,6 +7038,30 @@
             close
         """
 
+        pkg_overlayer_move = """
+            open overlayer-move@0,5.11-0
+            add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=true
+            close
+            open overlayer-move@1,5.11-0
+            add file tmp/file3 path=etc/pam/pam.conf mode=644 owner=root group=sys preserve=true overlay=true original_name=overlayer-move:etc/pam.conf
+            close
+        """
+
+        pkg_overlayer_update = """
+            open overlayer-update@0,5.11-0
+            add file tmp/file1 path=etc/pam.conf mode=644 owner=root group=sys overlay=true
+            close
+            open overlayer-update@1,5.11-0
+            add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=true
+            close
+            open overlayer-update@2,5.11-0
+            add file tmp/file3 path=etc/pam.conf mode=644 owner=root group=sys preserve=renameold overlay=true
+            close
+            open overlayer-update@3,5.11-0
+            add file tmp/file4 path=etc/pam.conf mode=644 owner=root group=sys preserve=renamenew overlay=true
+            close
+        """
+
         pkg_multi_overlayer = """
             open multi-overlayer@0,5.11-0
             add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=true
@@ -6927,7 +7086,7 @@
 
         pkg_unpreserved_overlayer = """
             open unpreserved-overlayer@0,5.11-0
-            add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys overlay=true
+            add file tmp/unpreserved path=etc/pam.conf mode=644 owner=root group=sys overlay=true
             close
         """
 
@@ -7417,7 +7576,8 @@
             close
         """
 
-        misc_files = ["tmp/file1", "tmp/file2", "tmp/file3"]
+        misc_files = ["tmp/file1", "tmp/file2", "tmp/file3", "tmp/file4",
+            "tmp/unpreserved"]
 
         # Keep the depots around for the duration of the entire class
         persistent_setup = True
@@ -7541,7 +7701,7 @@
                 self.pkg("verify")
 
                 # Re-use the overlay packages for some preserve testing.
-                self.pkg("install overlaid")
+                self.pkg("install overlaid@0")
                 self.pkg("-D broken-conflicting-action-handling=1 install "
                     "invalid-overlayer")
                 # We may have been able to lay down the package, but because the
@@ -7595,6 +7755,11 @@
                 # (preserve does not have to be set).
                 self.image_create(self.rurl)
 
+                # Ensure boring package is installed as conflict checking is
+                # bypassed (and thus, overlay semantics) if all packages are
+                # removed from an image.
+                self.pkg("install boring")
+
                 # Should fail because one action specified overlay=allow,
                 # but not preserve (it isn't editable).
                 self.pkg("install invalid-overlaid")
@@ -7603,7 +7768,7 @@
 
                 # Should fail because one action is overlayable but overlaying
                 # action doesn't declare its intent to overlay.
-                self.pkg("install overlaid")
+                self.pkg("install overlaid@0")
                 self.file_contains("etc/pam.conf", "file1")
                 self.pkg("install invalid-overlayer", exit=1)
 
@@ -7635,7 +7800,7 @@
                 # Verify that the file isn't touched on uninstall of the
                 # overlaying package if package being overlaid is still
                 # installed.
-                self.pkg("uninstall overlayer")
+                self.pkg("uninstall -vvv overlayer")
                 self.file_contains("etc/pam.conf", "zigit")
                 self.file_contains("etc/pam.conf", "file2")
 
@@ -7646,7 +7811,7 @@
 
                 # Verify that installing both packages at the same time results
                 # in only the overlaying file being delivered.
-                self.pkg("install overlaid overlayer")
+                self.pkg("install overlaid@0 overlayer")
                 self.file_contains("etc/pam.conf", "file2")
 
                 # Verify that the file isn't touched on uninstall of the
@@ -7658,7 +7823,7 @@
 
                 # Re-install overlaid package and verify that file content
                 # does not change.
-                self.pkg("install overlaid")
+                self.pkg("install overlaid@0")
                 self.file_contains("etc/pam.conf", "file2")
                 self.file_contains("etc/pam.conf", "zigit")
                 self.pkg("uninstall overlaid overlayer")
@@ -7666,8 +7831,8 @@
                 # Should succeed because one action is overlayable and
                 # overlaying action declares its intent to overlay even
                 # though the overlaying action isn't marked with preserve.
-                self.pkg("install overlaid unpreserved-overlayer")
-                self.file_contains("etc/pam.conf", "file2")
+                self.pkg("install overlaid@0 unpreserved-overlayer")
+                self.file_contains("etc/pam.conf", "unpreserved")
 
                 # Should succeed because overlaid action permits modification
                 # and contents matches overlaying action.
@@ -7684,21 +7849,214 @@
 
                 # Should revert to content delivered by overlaying action.
                 self.pkg("fix unpreserved-overlayer")
-                self.file_contains("etc/pam.conf", "file2")
+                self.file_contains("etc/pam.conf", "unpreserved")
                 self.file_doesnt_contain("etc/pam.conf", "zigit")
 
                 # Should revert to content delivered by overlaying action.
                 self.file_append("etc/pam.conf", "zigit")
                 self.pkg("revert /etc/pam.conf")
-                self.file_contains("etc/pam.conf", "file2")
+                self.file_contains("etc/pam.conf", "unpreserved")
                 self.file_doesnt_contain("etc/pam.conf", "zigit")
                 self.pkg("uninstall unpreserved-overlayer")
 
                 # Should revert to content delivered by overlaid action.
-                self.file_contains("etc/pam.conf", "file2")
+                self.file_contains("etc/pam.conf", "unpreserved")
                 self.pkg("revert /etc/pam.conf")
                 self.file_contains("etc/pam.conf", "file1")
 
+                # Install overlaying package, then update overlaid package and
+                # verify that file content does not change if only preserve
+                # attribute changes.
+                self.pkg("install -vvv unpreserved-overlayer")
+                self.file_contains("etc/pam.conf", "unpreserved")
+                self.pkg("install overlaid@1")
+                self.file_contains("etc/pam.conf", "unpreserved")
+                self.pkg("uninstall -vvv overlaid")
+
+                # Now update overlaid package again, and verify that file
+                # content does not change even though overlaid content has.
+                self.pkg("install -vvv overlaid@2")
+                self.file_contains("etc/pam.conf", "unpreserved")
+
+                # Now update overlaid package again this time as part of a
+                # rename, and verify that file content does not change even
+                # though file has moved between packages.
+                self.pkg("install -vvv overlaid@3")
+                self.file_contains("etc/pam.conf", "unpreserved")
+
+                # Verify that unpreserved overlay is not salvaged when both
+                # overlaid and overlaying package are removed at the same time.
+                # (Preserved files are salvaged if they have been modified on
+                # uninstall.)
+
+                # Ensure directory is empty before testing.
+                api_inst = self.get_img_api_obj()
+                img_inst = api_inst.img
+                sroot = os.path.join(img_inst.imgdir, "lost+found")
+                shutil.rmtree(sroot)
+
+                # Verify etc directory not found after uninstall.
+                self.pkg("uninstall -vvv overlaid-renamed unpreserved-overlayer")
+                salvaged = [
+                    n for n in os.listdir(sroot)
+                    if n.startswith("etc")
+                ]
+                self.assertEqualDiff(salvaged, [])
+
+                # Next, update overlaid package again this time as part of a
+                # file move.  Verify that the configuration file exists at both
+                # the new location and the old location, that the content has
+                # not changed in either, and that the new configuration exists
+                # as expected as ".new".
+                self.pkg("install -vvv overlaid-renamed@3 unpreserved-overlayer")
+                self.pkg("install -vvv [email protected]")
+                self.file_contains("etc/pam.conf", "unpreserved")
+                self.file_contains("etc/pam/pam.conf", "unpreserved")
+                self.file_contains("etc/pam/pam.conf.new", "file4")
+
+                # Verify etc/pam.conf not salvaged after uninstall as overlay
+                # file has not been changed.
+                self.pkg("uninstall -vvv overlaid-renamed unpreserved-overlayer")
+                salvaged = [
+                    n for n in os.listdir(os.path.join(sroot, "etc"))
+                    if n.startswith("pam.conf")
+                ]
+                self.assertEqualDiff(salvaged, [])
+
+                # Next, repeat the same set of tests performed above for renames
+                # and moves with an overlaying, preserved file.
+                #
+                # Install overlaying package, then update overlaid package and
+                # verify that file content does not change if only preserve
+                # attribute changes.
+                self.pkg("install -vvv overlayer")
+                self.file_contains("etc/pam.conf", "file2")
+                self.file_append("etc/pam.conf", "zigit")
+                self.pkg("install overlaid@1")
+                self.file_contains("etc/pam.conf", "zigit")
+                self.pkg("uninstall -vvv overlaid")
+
+                # Now update overlaid package again, and verify that file
+                # content does not change even though overlaid content has.
+                self.pkg("install -vvv overlaid@2")
+                self.file_contains("etc/pam.conf", "zigit")
+
+                # Now update overlaid package again this time as part of a
+                # rename, and verify that file content does not change even
+                # though file has moved between packages.
+                self.pkg("install -vvv overlaid@3")
+                self.file_contains("etc/pam.conf", "zigit")
+
+                # Verify that preserved overlay is salvaged when both overlaid
+                # and overlaying package are removed at the same time.
+                # (Preserved files are salvaged if they have been modified on
+                # uninstall.)
+
+                # Ensure directory is empty before testing.
+                api_inst = self.get_img_api_obj()
+                img_inst = api_inst.img
+                sroot = os.path.join(img_inst.imgdir, "lost+found")
+                shutil.rmtree(sroot)
+
+                # Verify etc directory found after uninstall.
+                self.pkg("uninstall -vvv overlaid-renamed overlayer")
+                salvaged = [
+                    n for n in os.listdir(sroot)
+                    if n.startswith("etc")
+                ]
+                self.assertEqualDiff(salvaged, ["etc"])
+
+                # Next, update overlaid package again, this time as part of a
+                # file move where the overlay attribute was dropped.  Verify
+                # that the configuration file exists at both the new location
+                # and the old location, that the content has not changed in
+                # either, and that the new configuration exists as expected as
+                # ".new".
+                self.pkg("install -vvv overlaid-renamed@3 overlayer")
+                self.file_append("etc/pam.conf", "zigit")
+                self.pkg("install -vvv [email protected]")
+                self.file_contains("etc/pam.conf", "zigit")
+                self.file_contains("etc/pam/pam.conf", "zigit")
+                self.file_contains("etc/pam/pam.conf.new", "file4")
+                self.pkg("uninstall -vvv overlaid-renamed overlayer")
+
+                # Next, update overlaid package again, this time as part of a
+                # file move.  Verify that the configuration file exists at both
+                # the new location and the old location, that the content has
+                # not changed in either, and that the new configuration exists
+                # as expected as ".new".
+                self.pkg("install -vvv overlaid-renamed@3 overlayer")
+                self.file_append("etc/pam.conf", "zigit")
+                self.pkg("install -vvv [email protected]")
+                self.file_contains("etc/pam.conf", "zigit")
+                self.file_contains("etc/pam/pam.conf", "zigit")
+                self.file_contains("etc/pam/pam.conf.new", "file4")
+
+                # Next, downgrade the package and verify that if an overlaid
+                # file moves back to its original location, the content of the
+                # overlay file will not change.
+                self.pkg("update -vvv overlaid-renamed@3")
+                self.file_contains("etc/pam.conf", "zigit")
+
+                # Now upgrade again for remaining tests.
+                self.pkg("install -vvv [email protected]")
+
+                # Verify etc/pam.conf and etc/pam/pam.conf salvaged after
+                # uninstall as overlay file and overlaid file is different from
+                # packaged.
+                shutil.rmtree(sroot)
+                self.pkg("uninstall -vvv overlaid-renamed overlayer")
+                salvaged = sorted(
+                    n for n in os.listdir(os.path.join(sroot, "etc"))
+                    if n.startswith("pam")
+                )
+                # Should have three entries; one should be 'pam' directory
+                # (presumably containing pam.conf-X...), another a file starting
+                # with 'pam.conf', and finally a 'pam-XXX' directory containing
+                # the 'pam.conf.new-XXX'.
+                self.assertEqualDiff(salvaged[0], "pam")
+                self.assert_(salvaged[1].startswith("pam-"),
+                    msg=str(salvaged))
+                self.assert_(salvaged[2].startswith("pam.conf"),
+                    msg=str(salvaged))
+
+                # Next, install overlaid package and overlaying package, then
+                # upgrade each to a version where the file has changed
+                # locations and verify that the content remains intact.
+                self.pkg("install -vvv overlaid@0 overlayer-move@0")
+                self.file_append("etc/pam.conf", "zigit")
+                self.pkg("install -vvv overlaid@3")
+                self.file_contains("etc/pam.conf", "zigit")
+                self.pkg("install -vvv [email protected] overlayer-move@1")
+                self.file_contains("etc/pam/pam.conf", "zigit")
+
+                # Next, downgrade overlaid-renamed and overlaying package to
+                # versions where the file is restored to its original location
+                # and verify that the content is reverted to the original
+                # overlay version since this is a downgrade.
+                self.pkg("update -vvv overlaid-renamed@3 overlayer-move@0")
+                self.file_contains("etc/pam.conf", "file2")
+                self.pkg("uninstall overlaid-renamed overlayer-move")
+
+                # Next, install overlaid package and overlaying package and
+                # verify preserve acts as expected for overlay package as it is
+                # updated.
+                self.pkg("install -vvv overlaid@2 overlayer-update@0")
+                self.file_contains("etc/pam.conf", "file1")
+                # unpreserved -> preserved
+                self.pkg("install -vvv overlayer-update@1")
+                self.file_contains("etc/pam.conf", "file2")
+                self.file_append("etc/pam.conf", "zigit")
+                # preserved -> renameold
+                self.pkg("install -vvv overlayer-update@2")
+                self.file_doesnt_contain("etc/pam.conf", "zigit")
+                self.file_contains("etc/pam.conf.old", "zigit")
+                self.file_append("etc/pam.conf", "zagat")
+                # renameold -> renamenew
+                self.pkg("install -vvv overlayer-update@3")
+                self.file_contains("etc/pam.conf", "zagat")
+                self.file_contains("etc/pam.conf.new", "file4")
+
         def test_different_types(self):
                 """Test the behavior of pkg(1) when multiple actions of
                 different types deliver to the same pathname."""
@@ -8114,8 +8472,8 @@
                     "tripledupfilec")
                 self.pkg("-D broken-conflicting-action-handling=1 install "
                     "tripledupfilea")
-                self.pkg("change-variant variant.foo=two")
-                self.pkg("change-variant variant.foo=one", exit=1)
+                self.pkg("change-variant -vvv variant.foo=two")
+                self.pkg("change-variant -vvv variant.foo=one", exit=1)
 
         def dir_exists(self, path, mode=None, owner=None, group=None):
                 dir_path = os.path.join(self.get_img_path(), path)
--- a/src/tests/cli/t_pkg_linked.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_linked.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -39,6 +39,7 @@
 
 import pkg.actions
 import pkg.client.image as image
+import pkg.fmri as fmri
 
 from pkg.client.pkgdefs import *
 
@@ -88,8 +89,8 @@
                 p_all.append(p_data)
 
         # generate packages that do need to be synced
-        p_sunc1_name_gen = "sync1"
-        pkgs = [p_sunc1_name_gen + ver for ver in p_vers]
+        p_sync1_name_gen = "sync1"
+        pkgs = [p_sync1_name_gen + ver for ver in p_vers]
         p_sync1_name = dict(zip(range(len(pkgs)), pkgs))
         for i in p_sync1_name:
                 p_data = "open %s\n" % p_sync1_name[i]
@@ -114,7 +115,7 @@
                     add set name=variant.foo value=bar value=baz
                     add file tmp/bar mode=0555 owner=root group=bin path=sync2_bar variant.foo=bar
                     add file tmp/baz mode=0555 owner=root group=bin path=sync2_baz variant.foo=baz
-                     close\n"""
+                    close\n"""
                 p_all.append(p_data)
 
         def setUp(self):
@@ -241,7 +242,8 @@
                 # Ensure 'coverage' is turned off-- it won't work.
                 self.cmdline_run("%s" % args, exit=rv, coverage=False)
 
-        def _pkg(self, il, cmd, args=None, rv=None, rvdict=None):
+        def _pkg(self, il, cmd, args=None, rv=None, rvdict=None,
+            output_cb=None, env_arg=None):
                 assert type(il) == list
                 assert type(cmd) == str
                 assert args == None or type(args) == str
@@ -267,7 +269,9 @@
                 for i in il:
                         rv = rvdict.get(i, EXIT_OK)
                         self.pkg("-R %s %s %s" % (self.i_path[i], cmd, args),
-                            exit=rv)
+                            exit=rv, env_arg=env_arg)
+                        if output_cb:
+                                output_cb(self.output)
 
         def _pkg_child(self, i, cl, cmd, args=None, rv=None, rvdict=None):
                 assert type(i) == int
@@ -346,6 +350,9 @@
                             (args, self.i_name[c], self.i_path[c]),
                             rv=rv)
 
+        def _assertEqual_cb(self, output):
+                return lambda x: self.assertEqual(output, x)
+
 
 class TestPkgLinked1(TestPkgLinked):
         def test_not_linked(self):
@@ -1064,9 +1071,6 @@
                 self._pkg_child_all(0, "audit-linked")
 
 
-class TestPkgLinked2(TestPkgLinked):
-        """Class used solely to split up the test suite for parallelization."""
-
         def test_audit_diverged_1(self):
                 self._imgs_create(4)
 
@@ -1097,6 +1101,9 @@
                 self._pkg_child(0, [1, 2, 3], "audit-linked", rv=rv)
                 self._pkg_child_all(0, "audit-linked", rv=rv)
 
+class TestPkgLinked2(TestPkgLinked):
+        """Class used solely to split up the test suite for parallelization."""
+
         def test_sync_fail(self):
                 self._imgs_create(3)
 
@@ -1233,93 +1240,300 @@
                 self._pkg([1, 2], "list -v %s" % self.p_sync1_name[1])
                 self._pkg([1, 2], "list -v %s" % self.p_foo1_name[2])
 
-        def test_sync_2_via_image_update(self):
-                self._imgs_create(3)
-
-                # install different synced package into each image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[1])
-                self._pkg([1, 2], "install -v %s" % self.p_sync1_name[2])
-
-                # install unsynced packages to make sure they are updated
+        def __test_linked_sync_via_child_op(self, op, op_args, **kwargs):
+                """Verify that if we do a operation "op" on a child image, it
+                automatically brings its packages in sync with its parent.
+
+                We perform operation on three child images.  1 is a push
+                child, 2 and 3 are pull children.  1 and 2 have their linked
+                image metadata in sync with the parent.  3 has its metadata
+                out of sync with the parent and is expected to sync its own
+                metadata."""
+
+                # create parent (0), push child (1), and pull child (2, 3)
+                self._imgs_create(4)
+                self._attach_child(0, [1])
+                self._attach_parent([2, 3], 0)
+
+                # install synced package into each image
+                self._pkg([0, 1, 2, 3], "install -v %s" % self.p_sync1_name[2])
+
+                # install unsynced packages
                 self._pkg([0], "install -v %s" % self.p_foo1_name[1])
-                self._pkg([1, 2], "install -v %s" % self.p_foo1_name[2])
-
-                # use --linked-md-only so we don't install constraints package
-                self._attach_child(0, [1], args="--linked-md-only")
-                self._attach_parent([2], 0, args="--linked-md-only")
-
-                # plan sync
-                self._pkg([1, 2], "image-update -vn")
-                self._pkg([1, 2], "audit-linked", rv=EXIT_DIVERGED)
-
-                # sync child
-                self._pkg([1, 2], "image-update --parsable=0")
-                self.assertEqualParsable(self.output, change_packages=[
-                    [self.foo1_list[2], self.foo1_list[0]],
-                    [self.s1_list[2], self.s1_list[1]]])
-                self._pkg([1, 2], "audit-linked")
-                self._pkg([1, 2], "image-update -v", rv=EXIT_NOP)
-                self._pkg([1, 2], "sync-linked -v", rv=EXIT_NOP)
-
-                # check unsynced packages
-                self._pkg([1, 2], "list -v %s" % self.p_foo1_name[0])
-
-        def test_sync_2_via_install(self):
+                self._pkg([1, 2, 3], "install -v %s" % self.p_foo1_name[2])
+
+                # update the parent image while ignoring the children (there
+                # by putting them out of sync)
+                self._pkg([0], "install -I -v %s" % self.p_sync1_name[1])
+
+                # explicitly sync metadata in children 1 and 2
+                self._pkg([0], "sync-linked -a --linked-md-only")
+                self._pkg([2], "sync-linked --linked-md-only")
+
+                # plan op
+                self._pkg([1, 2, 3], "%s -nv %s" % (op, op_args))
+
+                # verify child images are still diverged
+                self._pkg([1, 2, 3], "audit-linked", rv=EXIT_DIVERGED)
+                self._pkg([0], "audit-linked -a", rv=EXIT_DIVERGED)
+
+                # verify child 3 hasn't updated its metadata
+                # (it still thinks it's in sync)
+                self._pkg([3], "audit-linked --no-parent-sync")
+
+                # execute op
+                def output_cb(output):
+                        self.assertEqualParsable(output, **kwargs)
+                self._pkg([1, 2, 3], "%s --parsable=0 %s" % (op, op_args),
+                    output_cb=output_cb)
+
+                # verify sync via audit and sync (which should be a noop)
+                self._pkg([1, 2, 3], "audit-linked")
+                self._pkg([1, 2, 3], "sync-linked -v", rv=EXIT_NOP)
+                self._pkg([0], "audit-linked -a")
+                self._pkg([0], "sync-linked -a", rv=EXIT_NOP)
+
+        def __test_linked_sync_via_parent_op(self, op, op_args,
+            li_md_change=True, **kwargs):
+                """Verify that if we do a operation "op" on a parent image, it
+                recurses into its children and brings them into sync.
+
+                We perform operation on two child images.  both are push
+                children.  1 has its linked image metadata in sync with the
+                parent.  2 has its linked image metadata out of in sync with
+                the parent and that metadata should get updated during the
+                operation.
+
+                Note that if the metadata in a child image is in sync with its
+                parent, a recursive operation that isn't changing that
+                metadata will assume that the child is already in sync and
+                that we don't need to recurse into it.  This optimization
+                occurs regardless of if the child image is actually in sync
+                with that metadata (a child can be out of sync with its
+                stored metadata if we do a metadata only update)."""
+
+                # create parent (0), push child (1, 2)
                 self._imgs_create(3)
-
-                # install different synced package into each image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[1])
-                self._pkg([1, 2], "install -v %s" % self.p_sync1_name[2])
-
-                # install unsynced packages to make sure they aren't molested
+                self._attach_child(0, [1, 2])
+
+                # install synced package into each image
+                self._pkg([0, 1, 2], "install -v %s" % self.p_sync1_name[2])
+
+                # install unsynced packages
                 self._pkg([0], "install -v %s" % self.p_foo1_name[1])
                 self._pkg([1, 2], "install -v %s" % self.p_foo1_name[2])
 
-                # use --linked-md-only so we don't install constraints package
-                self._attach_child(0, [1], args="--linked-md-only")
-                self._attach_parent([2], 0, args="--linked-md-only")
-
-                # plan sync
-                self._pkg([1, 2], "install -vn %s" % self.p_sync1_name[1])
-                self._pkg([1, 2], "audit-linked", rv=EXIT_DIVERGED)
-
-                # sync child
-                self._pkg([1, 2], "install -v %s" % self.p_sync1_name[1])
-                self._pkg([1, 2], "audit-linked")
-                self._pkg([1, 2], "install -v %s" % self.p_sync1_name[1],
-                    rv=EXIT_NOP)
-                self._pkg([1, 2], "sync-linked -v", rv=EXIT_NOP)
-
-                # check unsynced packages
-                self._pkg([1, 2], "list -v %s" % self.p_foo1_name[2])
-
-        def test_no_sync_2_via_change_variant(self):
-                self._imgs_create(3)
-
-                # install different synced package into each image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[1])
-                self._pkg([1, 2], "install -v %s" % self.p_sync1_name[2])
-
-                # install unsynced packages to make sure they aren't molested
-                self._pkg([0], "install -v %s" % self.p_foo1_name[1])
-                self._pkg([1, 2], "install -v %s" % self.p_foo1_name[2])
-
-                # use --linked-md-only so we don't install constraints package
-                self._attach_child(0, [1], args="--linked-md-only")
-                self._attach_parent([2], 0, args="--linked-md-only")
-
-                # plan sync
-                self._pkg([1, 2], "change-variant -vn variant.foo=baz")
-                self._pkg([1, 2], "audit-linked", rv=EXIT_DIVERGED)
-
-                # sync child
-                self._pkg([1, 2], "change-variant -v variant.foo=baz")
-                self._pkg([1, 2], "audit-linked", rv=EXIT_DIVERGED)
-                self._pkg([1, 2], "change-variant -v variant.foo=baz",
-                    rv=EXIT_NOP)
-
-                # check unsynced packages
-                self._pkg([1, 2], "list -v %s" % self.p_foo1_name[2])
+                # update the parent image while ignoring the children (there
+                # by putting them out of sync)
+                self._pkg([0], "install -I -v %s" % self.p_sync1_name[1])
+
+                # explicitly sync metadata in child 1
+                self._pkg([0], "sync-linked --linked-md-only -l %s" %
+                    self.i_name[1])
+
+                # plan op
+                self._pkg([0], "%s -nv %s" % (op, op_args))
+
+                # verify child images are still diverged
+                self._pkg([1], "audit-linked", rv=EXIT_DIVERGED)
+                self._pkg([0], "audit-linked -a", rv=EXIT_DIVERGED)
+
+                # verify child 2 hasn't updated its metadata
+                # (it still thinks it's in sync)
+                self._pkg([2], "audit-linked")
+
+                # execute op
+                def output_cb(output):
+                        self.assertEqualParsable(output, **kwargs)
+                self._pkg([0], "%s --parsable=0 %s" % (op, op_args),
+                    output_cb=output_cb)
+
+                # verify sync via audit and sync (which should be a noop)
+                # if the linked image metadata was changed during this
+                # operation we should have updated both children.  if linked
+                # image metadata was not changed, we'll only have updated one
+                # child.
+                if li_md_change:
+                        synced_children=[1, 2]
+                else:
+                        synced_children=[2]
+                for i in synced_children:
+                        self._pkg([i], "audit-linked")
+                        self._pkg([i], "sync-linked", rv=EXIT_NOP)
+                        self._pkg([0], "audit-linked -l %s" % self.i_name[i])
+                        self._pkg([0], "sync-linked -l %s" % self.i_name[i],
+                            rv=EXIT_NOP)
+
+        def test_linked_sync_via_update(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do an update."""
+
+                self.__test_linked_sync_via_child_op(
+                    "update", "",
+                    change_packages=[
+                        [self.foo1_list[2], self.foo1_list[0]],
+                        [self.s1_list[2], self.s1_list[1]]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "update", "",
+                    change_packages=[
+                        [self.foo1_list[1], self.foo1_list[0]],
+                        [self.s1_list[1], self.s1_list[0]]],
+                    child_images=[{
+                        "image_name": "system:img1",
+                        "change_packages": [
+                            [self.foo1_list[2], self.foo1_list[0]],
+                            [self.s1_list[2], self.s1_list[0]]],
+                        },{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.foo1_list[2], self.foo1_list[0]],
+                            [self.s1_list[2], self.s1_list[0]]],
+                    }])
+
+        def test_linked_sync_via_update_pkg(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do an update of a specific
+                package."""
+
+                self.__test_linked_sync_via_child_op(
+                    "update", self.p_foo1_name[3],
+                    change_packages=[
+                        [self.foo1_list[2], self.foo1_list[3]],
+                        [self.s1_list[2], self.s1_list[1]]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "update", self.p_foo1_name[3],
+                    change_packages=[
+                        [self.foo1_list[1], self.foo1_list[3]]],
+                    child_images=[{
+                        "image_name": "system:img1",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                        },{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
+
+        def test_linked_sync_via_install(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do an install."""
+
+                self.__test_linked_sync_via_child_op(
+                    "install", self.p_foo1_name[1],
+                    change_packages=[
+                        [self.foo1_list[2], self.foo1_list[1]],
+                        [self.s1_list[2], self.s1_list[1]]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "install", self.p_foo1_name[0],
+                    change_packages=[
+                        [self.foo1_list[1], self.foo1_list[0]],
+                    ],
+                    child_images=[{
+                        "image_name": "system:img1",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                        },{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
+
+        def test_linked_sync_via_sync(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do a sync-linked."""
+
+                self.__test_linked_sync_via_child_op(
+                    "sync-linked", "",
+                    change_packages=[
+                        [self.s1_list[2], self.s1_list[1]]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "sync-linked", "-a",
+                    child_images=[{
+                        "image_name": "system:img1",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                        },{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
+
+        def test_linked_sync_via_change_variant(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do a change-variant."""
+
+                self.__test_linked_sync_via_child_op(
+                    "change-variant", "variant.foo=baz",
+                    change_packages=[
+                        [self.s1_list[2], self.s1_list[1]]],
+                    affect_packages=[
+                        self.foo1_list[2]],
+                    change_variants=[
+                        ['variant.foo', 'baz']])
+
+                self.__test_linked_sync_via_parent_op(
+                    "change-variant", "variant.foo=baz",
+                    li_md_change=False,
+                    affect_packages=[
+                        self.foo1_list[1], self.s1_list[1]],
+                    change_variants=[
+                        ['variant.foo', 'baz']],
+                    child_images=[{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
+
+        def test_linked_sync_via_change_facet(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do a change-facet."""
+
+                self.__test_linked_sync_via_child_op(
+                    "change-facet", "facet.foo=True",
+                    change_packages=[
+                        [self.s1_list[2], self.s1_list[1]]],
+                    change_facets=[
+                        ['facet.foo', True, None, 'local', False, False]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "change-facet", "facet.foo=True",
+                    li_md_change=False,
+                    change_facets=[
+                        ['facet.foo', True, None, 'local', False, False]],
+                    child_images=[{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
+
+        def test_linked_sync_via_uninstall(self):
+                """Verify that if we update child images to be in sync with
+                their constraints when we do an uninstall."""
+
+                self.__test_linked_sync_via_child_op(
+                    "uninstall", self.p_foo1_name[2],
+                    change_packages=[
+                        [self.s1_list[2], self.s1_list[1]]],
+                    remove_packages=[
+                        self.foo1_list[2]])
+
+                self.__test_linked_sync_via_parent_op(
+                    "uninstall", self.foo1_list[1],
+                    remove_packages=[
+                        self.foo1_list[1]],
+                    child_images=[{
+                        "image_name": "system:img1",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                        },{
+                        "image_name": "system:img2",
+                        "change_packages": [
+                            [self.s1_list[2], self.s1_list[1]]],
+                    }])
 
 
 class TestPkgLinked3(TestPkgLinked):
@@ -1338,12 +1552,15 @@
 
                 # there should be no updates with --no-parent-sync
                 self._pkg([1], "sync-linked -v --no-parent-sync", rv=EXIT_NOP)
-                self._pkg([1], "image-update -v --no-parent-sync", rv=EXIT_NOP)
-                self._pkg([1], "install -v --no-parent-sync %s" % \
-                    self.p_sync1_name[1], rv=EXIT_NOP)
                 self._pkg([1], "change-variant -v --no-parent-sync "
                     "variant.foo=bar", rv=EXIT_NOP)
-                # TODO: test set-property-linked
+                self._pkg([1], "change-facet -v --no-parent-sync "
+                    "facet.foo=False")
+                self._pkg([1], "install -v --no-parent-sync %s" % \
+                    self.p_foo1_name[1])
+                self._pkg([1], "update -v --no-parent-sync")
+                self._pkg([1], "uninstall -v --no-parent-sync %s" % \
+                    self.p_foo1_name[0])
 
                 # an audit without a parent sync should thingk we're in sync
                 self._pkg([1], "audit-linked --no-parent-sync")
@@ -1355,75 +1572,6 @@
                 # should still be out of sync.
                 self._pkg([1], "audit-linked", rv=EXIT_DIVERGED)
 
-        def test_parent_sync_2_via_sync(self):
-                self._imgs_create(2)
-
-                # install synced package into each image
-                self._pkg([0, 1], "install -v %s" % self.p_sync1_name[1])
-
-                self._attach_parent([1], 0)
-
-                # update parent image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[0])
-
-                # verify that pkg operations sync parent metadata
-                self._pkg([1], "sync-linked -v -n")
-                self._pkg([1], "sync-linked -v")
-                self._pkg([1], "sync-linked -v", rv=EXIT_NOP)
-                self._pkg([1], "audit-linked")
-
-        def test_parent_sync_2_via_image_update(self):
-                self._imgs_create(2)
-
-                # install synced package into each image
-                self._pkg([0, 1], "install -v %s" % self.p_sync1_name[1])
-
-                self._attach_parent([1], 0)
-
-                # update parent image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[0])
-
-                # verify that pkg operations sync parent metadata
-                self._pkg([1], "image-update -v -n")
-                self._pkg([1], "image-update -v")
-                self._pkg([1], "image-update -v", rv=EXIT_NOP)
-                self._pkg([1], "audit-linked")
-
-        def test_parent_sync_2_via_install(self):
-                self._imgs_create(2)
-
-                # install synced package into each image
-                self._pkg([0, 1], "install -v %s" % self.p_sync1_name[1])
-
-                self._attach_parent([1], 0)
-
-                # update parent image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[0])
-
-                # verify that pkg operations sync parent metadata
-                self._pkg([1], "install -v -n %s" % self.p_sync1_name[0])
-                self._pkg([1], "install -v %s" % self.p_sync1_name[0])
-                self._pkg([1], "install -v %s" % self.p_sync1_name[0],
-                    rv=EXIT_NOP)
-                self._pkg([1], "audit-linked")
-
-        def test_parent_no_sync_2_via_change_variant(self):
-                self._imgs_create(2)
-
-                # install synced package into each image
-                self._pkg([0, 1], "install -v %s" % self.p_sync1_name[1])
-
-                self._attach_parent([1], 0)
-
-                # update parent image
-                self._pkg([0], "install -v %s" % self.p_sync1_name[0])
-
-                # verify that pkg operations sync parent metadata
-                self._pkg([1], "change-variant -v -n variant.foo=baz")
-                self._pkg([1], "change-variant -v variant.foo=baz")
-                self._pkg([1], "change-variant -v variant.foo=baz", rv=EXIT_NOP)
-                self._pkg([1], "audit-linked", rv=EXIT_DIVERGED)
-
         def test_install_constrainted(self):
                 self._imgs_create(3)
 
@@ -1450,75 +1598,6 @@
                 # install the same ver of a synced package in the child
                 self._pkg([1, 2], "install -v %s" % self.p_sync1_name[1])
 
-        def test_p2c_recurse_1_image_update(self):
-                self._imgs_create(3)
-
-                # install different synced package into each image
-                for i in [0, 1]:
-                        self._pkg([i], "install -v %s" % self.p_sync1_name[1])
-                for i in [2]:
-                        self._pkg([i], "install -v %s" % self.p_sync1_name[2])
-
-                # attach --linked-md-only doesn't install constraints package
-                self._attach_child(0, [1])
-                self._attach_child(0, [2], args="--linked-md-only")
-
-                self._pkg([0], "image-update -v -n")
-                self._pkg([0], "image-update --parsable=0")
-                self.assertEqualParsable(self.output,
-                    change_packages=[[self.s1_list[1], self.s1_list[0]]],
-                    child_images=[{
-                        "image_name": "system:img1",
-                        "change_packages": [[self.s1_list[1], self.s1_list[0]]],
-                    },
-                    {
-                        "image_name": "system:img2",
-                        "change_packages": [[self.s1_list[2], self.s1_list[0]]],
-                    }])
-                self._pkg([0], "image-update -v", rv=EXIT_NOP)
-
-                # make sure the latest synced packaged is in every image
-                for i in [0, 1, 2]:
-                        self._pkg([i], "list -v %s " % self.p_sync1_name[0])
-
-                # children should be synced
-                self._pkg([1, 2], "audit-linked")
-
-        def test_p2c_recurse_1_install_1(self):
-                self._imgs_create(3)
-
-                # install different synced package into each image
-                for i in [0, 1]:
-                        self._pkg([i], "install -v %s" % self.p_sync1_name[1])
-                for i in [2]:
-                        self._pkg([i], "install -v %s" % self.p_sync1_name[2])
-
-                # attach --linked-md-only doesn't install constraints package
-                self._attach_child(0, [1])
-                self._attach_child(0, [2], args="--linked-md-only")
-
-                self._pkg([0], "install -v -n %s" % self.p_sync1_name[0])
-                self._pkg([0], "install --parsable=0 %s" % self.p_sync1_name[0])
-                self.assertEqualParsable(self.output,
-                    change_packages=[[self.s1_list[1], self.s1_list[0]]],
-                    child_images=[{
-                        "image_name": "system:img1",
-                        "change_packages": [[self.s1_list[1], self.s1_list[0]]],
-                    },
-                    {
-                        "image_name": "system:img2",
-                        "change_packages": [[self.s1_list[2], self.s1_list[0]]],
-                    }])
-                self._pkg([0], "install -v %s" % self.p_sync1_name[0],
-                    rv=EXIT_NOP)
-
-                # make sure the latest synced packaged is in every image
-                for i in [0, 1, 2]:
-                        self._pkg([i], "list -v %s " % self.p_sync1_name[0])
-
-                # children should be synced
-                self._pkg([1, 2], "audit-linked")
-
         def test_verify(self):
                 self._imgs_create(5)
 
@@ -1548,5 +1627,1637 @@
                 self._pkg([0], "update --stage=prepare")
                 self._pkg([0], "update --stage=execute")
 
+        def __test_missing_parent_pkgs_metadata(self,
+            install="", audit_rv=EXIT_OK):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent package metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # paths for the linked image metadata files
+                md_files = [
+                        "%s/var/pkg/linked/linked_ppkgs" % self.i_path[i]
+                        for i in [1, 2]
+                ]
+
+                if install:
+                        for i in [0, 1, 2]:
+                                self._pkg([i], "install -v %s" % install)
+
+                # delete linked image metadata files
+                for f in md_files:
+                        self.file_exists(f)
+                        self._ccmd("rm %s" % f)
+
+                # verify that audit-linked can handle missing metadata.
+                self._pkg([0], "audit-linked -a")
+                self._pkg([2], "audit-linked")
+                self._pkg([1], "audit-linked", rv=audit_rv)
+                self._pkg([2], "audit-linked --no-parent-sync", rv=audit_rv)
+
+                # since we haven't modified the image, make sure the
+                # facet metadata files weren't re-created.
+                for f in md_files:
+                        self.file_doesnt_exist(f)
+
+                # verify that sync-linked can handle missing metadata.
+                # also verify that the operation will succeed and is
+                # not a noop (since it needs to update the metadata).
+                self._pkg([0], "sync-linked -a -n")
+                self._pkg([2], "sync-linked -n")
+
+                # since we haven't modified the image, make sure the
+                # facet metadata files weren't re-created.
+                for f in md_files:
+                        self.file_doesnt_exist(f)
+
+                # do a sync and verify that the files get created
+                self._pkg([0], "sync-linked -a")
+                self._pkg([2], "sync-linked")
+                for f in md_files:
+                        self.file_exists(f)
+
+        def test_missing_parent_pkgs_metadata_1(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent package metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test when parent has no packages installed.  The children also
+                have no packages installed so they are always in sync."""
+                self.__test_missing_parent_pkgs_metadata()
+
+        def test_missing_parent_pkgs_metadata_2(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent package metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test when parent and children have sync packages installed.
+                This means the children are diverged if their parent package
+                metadata is missing."""
+                self.__test_missing_parent_pkgs_metadata(
+                    install=self.p_sync1_name[0], audit_rv=EXIT_DIVERGED)
+
+        def __test_missing_parent_publisher_metadata(self,
+            clear_pubs=False):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent publisher metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # paths for the linked image metadata files
+                md_files = [
+                        "%s/var/pkg/linked/linked_ppubs" % self.i_path[i]
+                        for i in [1, 2]
+                ]
+
+                if clear_pubs:
+                        self._pkg([0, 1, 2], "unset-publisher test")
+
+                # delete linked image metadata files
+                for f in md_files:
+                        self.file_exists(f)
+                        self._ccmd("rm %s" % f)
+
+                # verify that audit-linked can handle missing metadata.
+                self._pkg([0], "audit-linked -a")
+                self._pkg([1, 2], "audit-linked")
+                self._pkg([2], "audit-linked --no-parent-sync")
+
+                # since we haven't modified the image, make sure the
+                # facet metadata files weren't re-created.
+                for f in md_files:
+                        self.file_doesnt_exist(f)
+
+                # verify that sync-linked can handle missing metadata.
+                # also verify that the operation will succeed and is
+                # not a noop (since it needs to update the metadata).
+                self._pkg([0], "sync-linked -a -n")
+                self._pkg([2], "sync-linked -n")
+
+                # since we haven't modified the image, make sure the
+                # facet metadata files weren't re-created.
+                for f in md_files:
+                        self.file_doesnt_exist(f)
+
+                # do a sync and verify that the files get created
+                self._pkg([0], "sync-linked -a")
+                self._pkg([2], "sync-linked")
+                for f in md_files:
+                        self.file_exists(f)
+
+        def test_missing_parent_publisher_metadata_1(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent publisher metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test when parent has no publishers configured."""
+                self.__test_missing_parent_publisher_metadata(
+                    clear_pubs=True)
+
+        def test_missing_parent_publisher_metadata_2(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent publisher metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test when parent has publishers configured."""
+                self.__test_missing_parent_publisher_metadata()
+
+
+class TestFacetInheritance(TestPkgLinked):
+        """Class to test facet inheritance between images.
+
+        These tests focus specifically on facet propagation from parent to
+        child images, masked facet handling, and facet reporting.  These tests
+        do not attempt to verify that the packaging system correctly handles
+        operations when facets and packages are changing at the same time."""
+
+        p_files = [
+            "tmp/foo1",
+            "tmp/foo2",
+            "tmp/foo3",
+            "tmp/sync1",
+            "tmp/sync2",
+            "tmp/sync3",
+        ]
+        p_foo_template = """
+            open foo@%(ver)d
+            add file tmp/foo1 mode=0555 owner=root group=bin path=foo1_foo1 facet.foo1=true
+            add file tmp/foo2 mode=0555 owner=root group=bin path=foo1_foo2 facet.foo2=true
+            add file tmp/foo3 mode=0555 owner=root group=bin path=foo1_foo3 facet.foo3=true
+            close"""
+        p_sync1_template = """
+            open sync1@%(ver)d
+            add file tmp/sync1 mode=0555 owner=root group=bin path=sync1_sync1 facet.sync1=true
+            add file tmp/sync2 mode=0555 owner=root group=bin path=sync1_sync2 facet.sync2=true
+            add file tmp/sync3 mode=0555 owner=root group=bin path=sync1_sync3 facet.sync3=true
+            add depend type=parent fmri=feature/package/dependency/self
+            close"""
+        p_sync2_template = """
+            open sync2@%(ver)d
+            add file tmp/sync1 mode=0555 owner=root group=bin path=sync2_sync1 facet.sync1=true
+            add file tmp/sync2 mode=0555 owner=root group=bin path=sync2_sync2 facet.sync2=true
+            add file tmp/sync3 mode=0555 owner=root group=bin path=sync2_sync3 facet.sync3=true
+            add depend type=parent fmri=feature/package/dependency/self
+            close"""
+        p_inc1_template = """
+            open inc1@%(ver)d
+            add depend type=require fmri=sync1
+            add depend type=incorporate fmri=sync1@%(ver)d facet.123456=true
+            add depend type=parent fmri=feature/package/dependency/self
+            close"""
+        p_inc2_template = """
+            open inc2@%(ver)d
+            add depend type=require fmri=sync2
+            add depend type=incorporate fmri=sync2@%(ver)d facet.456789=true
+            add depend type=parent fmri=feature/package/dependency/self
+            close"""
+
+        p_data_template = [
+            p_foo_template,
+            p_sync1_template,
+            p_sync2_template,
+            p_inc1_template,
+            p_inc2_template,
+        ]
+        p_data = []
+        for i in range(2):
+                for j in p_data_template:
+                        p_data.append(j % {"ver": (i + 1)})
+        p_fmri = {}
+
+        def setUp(self):
+                self.i_count = 3
+                pkg5unittest.ManyDepotTestCase.setUp(self, ["test"],
+                    image_count=self.i_count)
+
+                # create files that go in packages
+                self.make_misc_files(self.p_files)
+
+                # get repo url
+                self.rurl1 = self.dcs[1].get_repo_url()
+
+                # populate repository
+                for p in self.p_data:
+                        fmristr = self.pkgsend_bulk(self.rurl1, p)[0]
+                        f = fmri.PkgFmri(fmristr, "5.11")
+                        pkgstr = "%s@%s" % (f.pkg_name, f.version.release)
+                        self.p_fmri[pkgstr] = fmristr
+
+                # setup image names and paths
+                self.i_name = []
+                self.i_path = []
+                self.i_api = []
+                self.i_api_reset = []
+                for i in range(self.i_count):
+                        name = "system:img%d" % i
+                        self.i_name.insert(i, name)
+                        self.i_path.insert(i, self.img_path(i))
+
+        def test_facet_inheritance(self):
+                """Verify basic facet inheritance functionality for both push
+                and pull children."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # install packages with inheritable facets in all images
+                self._pkg([0, 1, 2], "install -v %s" % self.p_fmri["inc1@2"])
+                self._pkg([0, 1, 2], "install -v %s" % self.p_fmri["inc2@2"])
+
+                # verify that there are no facets set in any images
+                self._pkg([0, 1, 2], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(""))
+
+                # set some random facets and make sure they aren't inherited
+                # or affected by inherited facets
+                output = {}
+                for i in [0, 1, 2]:
+                        i2 = i + 1
+                        self._pkg([i], "change-facet "
+                            "sync%d=False foo%d=True" % (i2, i2))
+                for i in [0, 1, 2]:
+                        i2 = i + 1
+                        output = \
+                            "facet.foo%d\tTrue\tlocal\n" % i2 + \
+                            "facet.sync%d\tFalse\tlocal\n" % i2
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+
+                # disable an inheritable facet and verify it gets inherited
+                self._pkg([0], "change-facet 123456=False")
+                self._pkg([2], "sync-linked")
+                for i in [1, 2]:
+                        i2 = i + 1
+                        output = \
+                            "facet.123456\tFalse\tparent\n" + \
+                            "facet.foo%d\tTrue\tlocal\n" % i2 + \
+                            "facet.sync%d\tFalse\tlocal\n" % i2
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+
+                # enable an inheritable facet and verify it doesn't get
+                # inherited
+                self._pkg([0], "change-facet 123456=True")
+                self._pkg([2], "sync-linked")
+                for i in [1, 2]:
+                        i2 = i + 1
+                        output = \
+                            "facet.foo%d\tTrue\tlocal\n" % i2 + \
+                            "facet.sync%d\tFalse\tlocal\n" % i2
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+
+                # clear an inheritable facet and verify it doesn't get
+                # inherited
+                self._pkg([0], "change-facet 123456=False")
+                self._pkg([2], "sync-linked")
+                self._pkg([0], "change-facet 123456=None")
+                self._pkg([2], "sync-linked")
+                for i in [1, 2]:
+                        i2 = i + 1
+                        output = \
+                            "facet.foo%d\tTrue\tlocal\n" % i2 + \
+                            "facet.sync%d\tFalse\tlocal\n" % i2
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+
+        def test_facet_inheritance_globs(self):
+                """Verify that all facet glob patterns which affect
+                inheritable facets get propagated to children."""
+
+                # create parent (0), push child (1)
+                self._imgs_create(2)
+                self._attach_child(0, [1])
+
+                self._pkg([0], "change-facet" +
+                    " 123456=False" +
+                    " 456789=True" +
+                    " *456*=False" +
+                    " *789=True" +
+                    " 123*=True")
+
+                # verify that no facets are inherited
+                output = ""
+                self._pkg([1], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(output))
+
+                # install packages with inheritable facets in the parent
+                self._pkg([0], "install -v %s" % self.p_fmri["inc1@2"])
+
+                # verify that three facets are inherited
+                output = ""
+                output += "facet.*456*\tFalse\tparent\n"
+                output += "facet.123*\tTrue\tparent\n"
+                output += "facet.123456\tFalse\tparent\n"
+                self._pkg([1], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(output))
+
+                # install packages with inheritable facets in the parent
+                self._pkg([0], "install -v %s" % self.p_fmri["inc2@2"])
+
+                # verify that five facets are inherited
+                output = ""
+                output += "facet.*456*\tFalse\tparent\n"
+                output += "facet.*789\tTrue\tparent\n"
+                output += "facet.123*\tTrue\tparent\n"
+                output += "facet.123456\tFalse\tparent\n"
+                output += "facet.456789\tTrue\tparent\n"
+                self._pkg([1], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(output))
+
+                # remove packages with inheritable facets in the parent
+                self._pkg([0], "uninstall -v %s" % self.p_fmri["inc1@2"])
+
+                # verify that three facets are inherited
+                output = ""
+                output += "facet.*456*\tFalse\tparent\n"
+                output += "facet.*789\tTrue\tparent\n"
+                output += "facet.456789\tTrue\tparent\n"
+                self._pkg([1], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(output))
+
+                # remove packages with inheritable facets in the parent
+                self._pkg([0], "uninstall -v %s" % self.p_fmri["inc2@2"])
+
+                # verify that no facets are inherited
+                output = ""
+                self._pkg([1], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(output))
+
+        def test_facet_inheritance_masked_system(self):
+                """Test reporting of system facets."""
+
+                # create image (0)
+                self._imgs_create(1)
+
+                # install a package with facets in the image
+                self._pkg([0], "install -v %s" % self.p_fmri["foo@2"])
+
+                # set a facet
+                self._pkg([0], "change-facet 'f*1'=False")
+
+                # verify masked output
+                output_am  = \
+                    "facet.f*1\tFalse\tlocal\tFalse\n" + \
+                    "facet.foo1\tFalse\tlocal\tFalse\n" + \
+                    "facet.foo2\tTrue\tsystem\tFalse\n" + \
+                    "facet.foo3\tTrue\tsystem\tFalse\n"
+                output_im  = \
+                    "facet.foo1\tFalse\tlocal\tFalse\n" + \
+                    "facet.foo2\tTrue\tsystem\tFalse\n" + \
+                    "facet.foo3\tTrue\tsystem\tFalse\n"
+                self._pkg([0], "facet -H -F tsv -m -a", \
+                    output_cb=self._assertEqual_cb(output_am))
+                self._pkg([0], "facet -H -F tsv -m -i", \
+                    output_cb=self._assertEqual_cb(output_im))
+
+        def test_facet_inheritance_masked_preserve(self):
+                """Test handling for masked facets
+
+                Verify that pre-existing local facet settings which get masked
+                by inherited facets get restored when the inherited facets go
+                away."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # install a package with inheritable facets in the parent
+                self._pkg([0], "install -v %s" % self.p_fmri["inc1@2"])
+
+                for fv in ["True", "False"]:
+
+                        # set inheritable facet locally in children
+                        self._pkg([1, 2], "change-facet 123456=%s" % fv)
+
+                        # disable inheritable facet in parent
+                        self._pkg([0], "change-facet 123456=False")
+                        self._pkg([2], "sync-linked")
+
+                        # verify inheritable facet is disabled in children
+                        output = "facet.123456\tFalse\tparent\n"
+                        output_m = \
+                            "facet.123456\tFalse\tparent\tFalse\n" + \
+                            "facet.123456\t%s\tlocal\tTrue\n" % fv
+                        for i in [1, 2]:
+                                self._pkg([i], "facet -H -F tsv", \
+                                    output_cb=self._assertEqual_cb(output))
+                                self._pkg([i], "facet -H -F tsv -m", \
+                                    output_cb=self._assertEqual_cb(output_m))
+
+                        # clear inheritable facet in the parent
+                        self._pkg([0], "change-facet 123456=None")
+                        self._pkg([2], "sync-linked")
+
+                        # verify the local child setting is restored
+                        output = "facet.123456\t%s\tlocal\n" % fv
+                        output_m = "facet.123456\t%s\tlocal\tFalse\n" % fv
+                        for i in [1, 2]:
+                                self._pkg([i], "facet -H -F tsv", \
+                                    output_cb=self._assertEqual_cb(output))
+                                self._pkg([i], "facet -H -F tsv -m", \
+                                    output_cb=self._assertEqual_cb(output_m))
+
+        def test_facet_inheritance_masked_update(self):
+                """Test handling for masked facets.
+
+                Verify that local facet changes can be made while inherited
+                facets masking the local settings exist."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # install a package with inheritable facets in the parent
+                self._pkg([0], "install -v %s" % self.p_fmri["inc1@2"])
+
+                # disable inheritable facet in parent
+                self._pkg([0], "change-facet 123456=False")
+                self._pkg([2], "sync-linked")
+
+                # clear inheritable facet in children
+                # the facet is not set in the child so this is a noop
+                self._pkg([1, 2], "change-facet 123456=None", rv=EXIT_NOP)
+
+                # verify inheritable facet is disabled in children
+                output = "facet.123456\tFalse\tparent\n"
+                output_m = "facet.123456\tFalse\tparent\tFalse\n"
+                for i in [1, 2]:
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+                        self._pkg([i], "facet -H -F tsv -m", \
+                            output_cb=self._assertEqual_cb(output_m))
+
+                for fv in ["True", "False"]:
+
+                        # set inheritable facet locally in children
+                        self._pkg([1, 2], "change-facet 123456=%s" % fv)
+
+                        # verify inheritable facet is disabled in children
+                        output = "facet.123456\tFalse\tparent\n"
+                        output_m = \
+                            "facet.123456\tFalse\tparent\tFalse\n" + \
+                            "facet.123456\t%s\tlocal\tTrue\n" % fv
+                        for i in [1, 2]:
+                                self._pkg([i], "facet -H -F tsv", \
+                                    output_cb=self._assertEqual_cb(output))
+                                self._pkg([i], "facet -H -F tsv -m", \
+                                    output_cb=self._assertEqual_cb(output_m))
+
+                        # re-set inheritable facet locall in children
+                        # this is a noop
+                        self._pkg([1, 2], "change-facet 123456=%s" % fv,
+                            rv=EXIT_NOP)
+
+                        # clear inheritable facet in the parent
+                        self._pkg([0], "change-facet 123456=None")
+                        self._pkg([2], "sync-linked")
+
+                        # verify the local child setting is restored
+                        output = "facet.123456\t%s\tlocal\n" % fv
+                        output_m = "facet.123456\t%s\tlocal\tFalse\n" % fv
+                        for i in [1, 2]:
+                                self._pkg([i], "facet -H -F tsv", \
+                                    output_cb=self._assertEqual_cb(output))
+                                self._pkg([i], "facet -H -F tsv -m", \
+                                    output_cb=self._assertEqual_cb(output_m))
+
+                        # disable inheritable facet in parent
+                        self._pkg([0], "change-facet 123456=False")
+                        self._pkg([2], "sync-linked")
+
+                # clear inheritable facet locally in children
+                self._pkg([1, 2], "change-facet 123456=None")
+
+                # verify inheritable facet is disabled in children
+                output = "facet.123456\tFalse\tparent\n"
+                output_m = "facet.123456\tFalse\tparent\tFalse\n"
+                for i in [1, 2]:
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(output))
+                        self._pkg([i], "facet -H -F tsv -m", \
+                            output_cb=self._assertEqual_cb(output_m))
+
+                # re-clear inheritable facet locally in children
+                # this is a noop
+                self._pkg([1, 2], "change-facet 123456=None", rv=EXIT_NOP)
+
+                # clear inheritable facet in the parent
+                self._pkg([0], "change-facet 123456=None")
+                self._pkg([2], "sync-linked")
+
+                # verify the local child setting is restored
+                for i in [1, 2]:
+                        self._pkg([i], "facet -H -F tsv", \
+                            output_cb=self._assertEqual_cb(""))
+                        self._pkg([i], "facet -H -F tsv -m", \
+                            output_cb=self._assertEqual_cb(""))
+
+        def __test_facet_inheritance_via_op(self, op):
+                """Verify that if we do a an "op" operation, the latest facet
+                data gets pushed/pulled to child images."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # install synced incorporations
+                self._pkg([0, 1, 2], "install -v %s %s" %
+                    (self.p_fmri["inc1@1"], self.p_fmri["foo@1"]))
+
+                # disable a random facet in all images
+                self._pkg([0, 1, 2], "change-facet -I foo=False")
+
+                # disable an inheritable facet in the parent while ignoring
+                # children.
+                self._pkg([0], "change-facet -I 123456=False")
+
+                # verify that the change hasn't been propagated to the child
+                output = "facet.foo\tFalse\tlocal\n"
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # do "op" in the parent and verify the latest facet data was
+                # pushed to the child
+                self._pkg([0], op)
+                output  = "facet.123456\tFalse\tparent\n"
+                output += "facet.foo\tFalse\tlocal\n"
+                self._pkg([1], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # do "op" in the child and verify the latest facet data was
+                # pulled from the parent.
+                self._pkg([2], op)
+                output  = "facet.123456\tFalse\tparent\n"
+                output += "facet.foo\tFalse\tlocal\n"
+                self._pkg([2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+        def test_facet_inheritance_via_noop_update(self):
+                """Verify that if we do a noop update operation, the
+                latest facet data still gets pushed/pulled to child images."""
+
+                self.__test_facet_inheritance_via_op(
+                    "update")
+
+        def test_facet_inheritance_via_noop_install(self):
+                """Verify that if we do a noop install operation, the
+                latest facet data still gets pushed/pulled to child images."""
+
+                self.__test_facet_inheritance_via_op(
+                    "install -v %s" % self.p_fmri["inc1@1"])
+
+        def test_facet_inheritance_via_noop_change_facet(self):
+                """Verify that if we do a noop change-facet operation on a
+                parent image, the latest facet data still gets pushed out to
+                child images."""
+
+                self.__test_facet_inheritance_via_op(
+                    "change-facet foo=False")
+
+        def test_facet_inheritance_via_uninstall(self):
+                """Verify that if we do an uninstall operation on a
+                parent image, the latest facet data still gets pushed out to
+                child images."""
+
+                self.__test_facet_inheritance_via_op(
+                    "uninstall -v %s" % self.p_fmri["foo@1"])
+
+        def test_facet_inheritance_cleanup_via_detach(self):
+                """Verify that if we detach a child linked image, that any
+                inherited facets go away."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # install synced incorporations
+                self._pkg([0, 1, 2], "install -v %s %s" %
+                    (self.p_fmri["inc1@1"], self.p_fmri["foo@1"]))
+
+                # disable a random facet in all images
+                self._pkg([0, 1, 2], "change-facet -I foo=False")
+
+                # disable an inheritable facet in the parent and make sure the
+                # change propagates to all children
+                self._pkg([0], "change-facet 123456=False")
+                self._pkg([2], "sync-linked")
+                output  = "facet.123456\tFalse\tparent\n"
+                output += "facet.foo\tFalse\tlocal\n"
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # simulate detaching children via metadata only
+                # verify the inherited facets don't get removed
+                self._pkg([0], "detach-linked --linked-md-only -n -l %s" %
+                    self.i_name[1])
+                self._pkg([2], "detach-linked --linked-md-only -n")
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # simulate detaching children
+                # verify the inherited facets don't get removed
+                self._pkg([0], "detach-linked -n -l %s" % self.i_name[1])
+                self._pkg([2], "detach-linked -n")
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # detach children via metadata only
+                # verify the inherited facets don't get removed
+                # (they can't get removed until we modify the image)
+                self._pkg([0], "detach-linked --linked-md-only -l %s" %
+                    self.i_name[1])
+                self._pkg([2], "detach-linked --linked-md-only")
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # re-attach children and sanity check facets
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # try to detach children with --no-pkg-updates
+                # verify this fails
+                # (removal of inherited facets is the equilivant of a
+                # change-facet operation, which requires updating all
+                # packages, but since we've specified no pkg updates this must
+                # fail.)
+                self._pkg([0], "detach-linked --no-pkg-updates -l %s" %
+                    self.i_name[1], rv=EXIT_OOPS)
+                self._pkg([2], "detach-linked --no-pkg-updates", rv=EXIT_OOPS)
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+                # detach children
+                # verify the inherited facets get removed
+                self._pkg([0], "detach-linked -l %s" % self.i_name[1])
+                self._pkg([2], "detach-linked")
+                output = "facet.foo\tFalse\tlocal\n"
+                self._pkg([1, 2], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+        def __test_missing_facet_inheritance_metadata(self, pfacets="",
+            cfacet_output=""):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent facet metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly."""
+
+                # create parent (0), push child (1), and pull child (2)
+                self._imgs_create(3)
+                self._attach_child(0, [1])
+                self._attach_parent([2], 0)
+
+                # paths for the linked image metadata files
+                md_files = [
+                        "%s/var/pkg/linked/linked_pfacets" % self.i_path[i]
+                        for i in [1, 2]
+                ]
+
+                # isntall foo into each image
+                self._pkg([0], "install -v %s" % self.p_fmri["foo@1"])
+
+                # install synced incorporation and package
+                self._pkg([0], "install -v %s" % self.p_fmri["inc1@1"])
+                self._pkg([2], "sync-linked")
+
+                if pfacets:
+                        self._pkg([0], "change-facet %s" % pfacets)
+                        self._pkg([2], "sync-linked")
+
+                # verify the child facet settings
+                self._pkg([1, 2], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(cfacet_output))
+
+                # verify that the child images are in sync.
+                # verify that a sync-linked is a noop
+                self._pkg([0], "audit-linked -a")
+                self._pkg([1, 2], "audit-linked")
+                self._pkg([0], "sync-linked -a -n", rv=EXIT_NOP)
+                self._pkg([2], "sync-linked -n", rv=EXIT_NOP)
+
+                # delete linked image metadata files
+                for f in md_files:
+                        self.file_exists(f)
+                        self._ccmd("rm %s" % f)
+
+                # verify the child facet settings
+                self._pkg([1, 2], "facet -H -F tsv", \
+                    output_cb=self._assertEqual_cb(cfacet_output))
+
+                # verify that audit-linked can handle missing metadata.
+                self._pkg([0], "audit-linked -a")
+                self._pkg([1, 2], "audit-linked")
+                self._pkg([2], "audit-linked --no-parent-sync")
+
+                # verify that sync-linked can handle missing metadata.
+                # also verify that the operation will succeed and is
+                # not a noop (since it needs to update the metadata).
+                self._pkg([0], "sync-linked -a -n")
+                self._pkg([2], "sync-linked -n")
+
+                # since we haven't modified the image, make sure the
+                # facet metadata files weren't re-created.
+                for f in md_files:
+                        self.file_doesnt_exist(f)
+
+                # do a sync and verify that the files get created
+                self._pkg([0], "sync-linked -a")
+                self._pkg([2], "sync-linked")
+                for f in md_files:
+                        self.file_exists(f)
+
+        def test_missing_facet_inheritance_metadata_1(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent facet metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test when there are no inherited facets present."""
+                self.__test_missing_facet_inheritance_metadata()
+
+        def test_missing_facet_inheritance_metadata_2(self):
+                """Verify that we can manipulate and update linked child
+                images which are missing their parent facet metadata.  Also
+                verify that when we update those children the metadata gets
+                updated correctly.
+
+                Test with inherited facets present"""
+                self.__test_missing_facet_inheritance_metadata(
+                    pfacets="123456=False",
+                    cfacet_output="facet.123456\tFalse\tparent\n")
+
+
+class TestConcurrentFacetChange(TestPkgLinked):
+        """Class to test that packaging operations work correctly when facets
+        are changing concurrently.
+
+        These tests do not focus on verifying that facets are propagated
+        correctly from parent to child images."""
+
+        p_misc = """
+            open misc@1,5.11-0
+            close"""
+        p_common = """
+            open common@1,5.11-0
+            close"""
+        p_AA_sync_template = """
+            open AA-sync@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add depend type=require fmri=common
+            add depend type=require fmri=A-incorp-sync
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            close"""
+        p_AB_sync_template = """
+            open AB-sync@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add depend type=require fmri=common
+            add depend type=require fmri=A-incorp-sync
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            close"""
+        p_BA_template = """
+            open BA@%(ver)d,5.11-0
+            add depend type=require fmri=common
+            add depend type=require fmri=B-incorp-sync
+            close"""
+        p_CA_template = """
+            open CA@%(ver)d,5.11-0
+            add depend type=require fmri=common
+            add depend type=require fmri=C-incorp
+            close"""
+        p_A_incorp_sync_template = """
+            open A-incorp-sync@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add depend type=incorporate fmri=AA-sync@%(ver)d facet.AA-sync=true
+            add depend type=incorporate fmri=AB-sync@%(ver)d facet.AA-sync=true
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            close"""
+        p_B_incorp_sync_template = """
+            open B-incorp-sync@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add depend type=incorporate fmri=BA@%(ver)d facet.BA=true
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            close"""
+        p_C_incorp_template = """
+            open C-incorp@%(ver)d,5.11-0
+            add depend type=incorporate fmri=CA@%(ver)d facet.CA=true
+            close"""
+        p_entire_sync_template = """
+            open entire-sync@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add depend type=require fmri=A-incorp-sync
+            add depend type=incorporate fmri=A-incorp-sync@%(ver)d \
+                facet.A-incorp-sync=true
+            add depend type=require fmri=B-incorp-sync
+            add depend type=incorporate fmri=B-incorp-sync@%(ver)d \
+                facet.B-incorp-sync=true
+            add depend type=require fmri=C-incorp
+            add depend type=incorporate fmri=C-incorp@%(ver)d \
+                facet.C-incorp=true
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            close"""
+
+        p_data_template = [
+            p_AA_sync_template,
+            p_AB_sync_template,
+            p_BA_template,
+            p_CA_template,
+            p_A_incorp_sync_template,
+            p_B_incorp_sync_template,
+            p_C_incorp_template,
+            p_entire_sync_template,
+        ]
+
+        p_data = [p_misc, p_common]
+        for i in range(4):
+                for j in p_data_template:
+                        p_data.append(j % {"ver": (i + 1)})
+        p_fmri = {}
+
+        def setUp(self):
+                self.i_count = 2
+                pkg5unittest.ManyDepotTestCase.setUp(self, ["test"],
+                    image_count=self.i_count)
+
+                # get repo url
+                self.rurl1 = self.dcs[1].get_repo_url()
+
+                # populate repository
+                for p in self.p_data:
+                        fmristr = self.pkgsend_bulk(self.rurl1, p)[0]
+                        f = fmri.PkgFmri(fmristr, "5.11")
+                        pkgstr = "%s@%s" % (f.pkg_name, f.version.release)
+                        self.p_fmri[pkgstr] = fmristr
+
+                # setup image names and paths
+                self.i_name = []
+                self.i_path = []
+                self.i_api = []
+                self.i_api_reset = []
+                for i in range(self.i_count):
+                        name = "system:img%d" % i
+                        self.i_name.insert(i, name)
+                        self.i_path.insert(i, self.img_path(i))
+
+        def __test_concurrent_facet_change_via_child_op(self,
+            op, op_args, extra_child_pkgs=None, child_variants=None,
+            child_pre_op_audit=True, **kwargs):
+                """Verify that if we do a operation "op" on a child image, it
+                automatically brings its packages in sync with its parent."""
+
+                # create parent (0) and pull child (1)
+                self._imgs_create(2)
+
+                # setup the parent image
+                parent_facets = [
+                    "facet.AA-sync=False",
+                    "facet.A-incorp-sync=False",
+                    "facet.BA=False",
+                ]
+                parent_pkgs = [
+                    "A-incorp-sync@3",
+                    "AA-sync@4",
+                    "B-incorp-sync@2",
+                    "BA@3",
+                    "C-incorp@2",
+                    "CA@2",
+                    "entire-sync@2",
+                ]
+                self._pkg([0], "change-facet -v %s" % " ".join(parent_facets))
+                self._pkg([0], "install -v %s" % " ".join(parent_pkgs))
+
+                # setup the child image
+                child_facets = [
+                    "facet.C*=False",
+                ]
+                child_pkgs = [
+                    "A-incorp-sync@1",
+                    "AA-sync@1",
+                    "B-incorp-sync@1",
+                    "BA@1",
+                    "C-incorp@1",
+                    "CA@1",
+                    "entire-sync@1",
+                ]
+                self._pkg([1], "change-facet -v %s" % " ".join(child_facets))
+                if child_variants is not None:
+                        self._pkg([1], "change-variant -v %s" %
+                            " ".join(child_variants))
+                self._pkg([1], "install -v %s" % " ".join(child_pkgs))
+                if extra_child_pkgs:
+                        self._pkg([1], "install -v %s" %
+                            " ".join(extra_child_pkgs))
+
+                # attach the child but don't sync it
+                self._attach_parent([1], 0, args="--linked-md-only")
+
+                # verify the child image is still diverged
+                if child_pre_op_audit:
+                        self._pkg([1], "audit-linked", rv=EXIT_DIVERGED)
+
+                # try and then execute op
+                def output_cb(output):
+                        self.assertEqualParsable(output, **kwargs)
+                self._pkg([1], "%s -nv %s" % (op, op_args))
+                self._pkg([1], "%s --parsable=0 %s" % (op, op_args),
+                    output_cb=output_cb)
+
+                # verify sync via audit and sync (which should be a noop)
+                self._pkg([1], "audit-linked")
+                self._pkg([1], "sync-linked -v", rv=EXIT_NOP)
+
+        def __pkg_names_to_fmris(self, remove_packages):
+                """Convert a list of pkg names to fmris"""
+                rv = []
+                for s in remove_packages:
+                        rv.append(self.p_fmri[s])
+                return rv
+
+        def __pkg_name_tuples_to_fmris(self, change_packages):
+                """Convert a list of pkg name tuples to fmris"""
+                rv = []
+                for s, d in change_packages:
+                        rv.append([self.p_fmri[s], self.p_fmri[d]])
+                return rv
+
+        def test_concurrent_facet_change_via_update(self):
+                """Verify that we can update and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ['facet.A-incorp-sync',
+                        False, None, 'parent', False, False],
+                    ['facet.AA-sync', False, None, 'parent', False, False],
+                ]
+                remove_packages = self.__pkg_names_to_fmris([
+                    "AB-sync@1",
+                ])
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["C-incorp@1",      "C-incorp@4"],
+                    ["CA@1",            "CA@4"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "update", "--reject AB-sync",
+                    extra_child_pkgs=["AB-sync@1"],
+                    change_facets=change_facets,
+                    remove_packages=remove_packages,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_update_pkg(self):
+                """Verify that we can update a package and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ['facet.A-incorp-sync',
+                        False, None, 'parent', False, False],
+                    ['facet.AA-sync', False, None, 'parent', False, False],
+                ]
+                remove_packages = self.__pkg_names_to_fmris([
+                    "AB-sync@1",
+                ])
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+
+                # verify update pkg
+                self.__test_concurrent_facet_change_via_child_op(
+                    "update", "--reject AB-sync common",
+                    extra_child_pkgs=["AB-sync@1"],
+                    change_facets=change_facets,
+                    remove_packages=remove_packages,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_install(self):
+                """Verify that we can install a package and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ['facet.A-incorp-sync',
+                        False, None, 'parent', False, False],
+                    ['facet.AA-sync', False, None, 'parent', False, False],
+                ]
+                remove_packages = self.__pkg_names_to_fmris([
+                    "AB-sync@1",
+                ])
+                add_packages = self.__pkg_names_to_fmris([
+                    "misc@1",
+                ])
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "install", "--reject AB-sync misc",
+                    extra_child_pkgs=["AB-sync@1"],
+                    change_facets=change_facets,
+                    remove_packages=remove_packages,
+                    add_packages=add_packages,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_sync(self):
+                """Verify that we can sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ['facet.A-incorp-sync',
+                        False, None, 'parent', False, False],
+                    ['facet.AA-sync', False, None, 'parent', False, False],
+                ]
+                remove_packages = self.__pkg_names_to_fmris([
+                    "AB-sync@1",
+                ])
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "sync-linked", "--reject AB-sync",
+                    extra_child_pkgs=["AB-sync@1"],
+                    change_facets=change_facets,
+                    remove_packages=remove_packages,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_uninstall(self):
+                """Verify that we can uninstall a package and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ['facet.A-incorp-sync',
+                        False, None, 'parent', False, False],
+                    ['facet.AA-sync', False, None, 'parent', False, False],
+                ]
+                remove_packages = self.__pkg_names_to_fmris([
+                    "AB-sync@1",
+                ])
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "uninstall", "AB-sync",
+                    extra_child_pkgs=["AB-sync@1"],
+                    change_facets=change_facets,
+                    remove_packages=remove_packages,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_change_variant(self):
+                """Verify that we can change variants and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ["facet.A-incorp-sync",
+                        False, None, "parent", False, False],
+                    ["facet.AA-sync", False, None, "parent", False, False],
+                ]
+                change_variants = [
+                    ["variant.foo", "bar"]
+                ]
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "change-variant", "variant.foo=bar",
+                    child_variants=["variant.foo=baz"],
+                    child_pre_op_audit=False,
+                    change_facets=change_facets,
+                    change_variants=change_variants,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_change_facets(self):
+                """Verify that we can change facets and sync a child
+                image while inherited facets are changing."""
+
+                change_facets = [
+                    ["facet.A-incorp-sync",
+                        False, None, "parent", False, False],
+                    ["facet.AA-sync", False, None, "parent", False, False],
+                    ["facet.C-incorp", True, None, "local", False, False],
+                ]
+                change_packages = self.__pkg_name_tuples_to_fmris([
+                    ["A-incorp-sync@1", "A-incorp-sync@3"],
+                    ["AA-sync@1",       "AA-sync@4"],
+                    ["B-incorp-sync@1", "B-incorp-sync@2"],
+                    ["BA@1",            "BA@2"],
+                    ["C-incorp@1",      "C-incorp@2"],
+                    ["entire-sync@1",   "entire-sync@2"],
+                ])
+                self.__test_concurrent_facet_change_via_child_op(
+                    "change-facet", "facet.C-incorp=True",
+                    change_facets=change_facets,
+                    change_packages=change_packages)
+
+        def test_concurrent_facet_change_via_detach(self):
+                """Verify that we can detach a child image which has inherited
+                facets that when removed require updating the image."""
+
+                # create parent (0) and pull child (1)
+                self._imgs_create(2)
+
+                # setup the parent image
+                parent_facets = [
+                    "facet.AA-sync=False",
+                    "facet.A-incorp-sync=False",
+                ]
+                parent_pkgs = [
+                    "A-incorp-sync@2",
+                    "AA-sync@1",
+                    "B-incorp-sync@3",
+                    "BA@3",
+                    "C-incorp@3",
+                    "CA@3",
+                    "entire-sync@3",
+                ]
+                self._pkg([0], "change-facet -v %s" % " ".join(parent_facets))
+                self._pkg([0], "install -v %s" % " ".join(parent_pkgs))
+
+                # attach the child.
+                self._attach_parent([1], 0)
+
+                # setup the child image
+                child_facets = [
+                    "facet.C*=False",
+                ]
+                child_pkgs = [
+                    "A-incorp-sync@2",
+                    "AA-sync@1",
+                    "B-incorp-sync@3",
+                    "BA@3",
+                    "C-incorp@2",
+                    "CA@2",
+                    "entire-sync@3",
+                ]
+                self._pkg([1], "change-facet -v %s" % " ".join(child_facets))
+                self._pkg([1], "install -v %s" % " ".join(child_pkgs))
+
+                # a request to detach the child without any package updates
+                # should fail.
+                self._pkg([1], "detach-linked -v --no-pkg-updates",
+                    rv=EXIT_OOPS)
+
+                # detach the child
+                self._pkg([1], "detach-linked -v")
+
+                # verify the contents of the child image
+                child_fmris = self.__pkg_names_to_fmris([
+                    "A-incorp-sync@3",
+                    "AA-sync@3",
+                    "B-incorp-sync@3",
+                    "BA@3",
+                    "C-incorp@2",
+                    "CA@2",
+                    "entire-sync@3",
+                ])
+                self._pkg([1], "list -v %s" % " ".join(child_fmris))
+                output  = "facet.C*\tFalse\tlocal\n"
+                self._pkg([1], "facet -H -F tsv",
+                    output_cb=self._assertEqual_cb(output))
+
+
+class TestLinkedInstallHoldRelax(TestPkgLinked):
+        """Class to test automatic install-hold relaxing of constrained
+        packages when doing different packaging operations.
+
+        When performing packaging operations, any package that has an install
+        hold, but also has dependency on itself in its parent, must have that
+        install hold relaxed if we expect to be able to bring the image in
+        sync with its parent."""
+
+        # the "common" package exists because the solver ignores
+        # install-holds unless the package containing them depends on a
+        # specific version of another package.  so all our packages depend on
+        # the "common" package.
+        p_common = """
+            open common@1,5.11-0
+            close"""
+        p_A_template = """
+            open A@%(ver)d,5.11-0
+            add set name=pkg.depend.install-hold value=A
+            add depend type=require fmri=common
+            add depend type=incorporate fmri=common@1
+            close"""
+        p_B_template = """
+            open B@%(ver)d,5.11-0
+            add set name=variant.foo value=bar value=baz
+            add set name=pkg.depend.install-hold value=B
+            add depend type=parent fmri=feature/package/dependency/self \
+                variant.foo=bar
+            add depend type=require fmri=common
+            add depend type=incorporate fmri=common@1
+            close"""
+        p_C_template = """
+            open C@%(ver)d,5.11-0
+            add set name=pkg.depend.install-hold value=C
+            add depend type=require fmri=common
+            add depend type=incorporate fmri=common@1
+            close"""
+        p_BB_template = """
+            open BB@%(ver)d,5.11-0
+            add depend type=require fmri=B
+            add depend type=incorporate fmri=B@%(ver)d
+            close"""
+        p_BC_template = """
+            open BC@%(ver)d,5.11-0
+            add depend type=require fmri=B
+            add depend type=incorporate fmri=B@%(ver)d
+            add depend type=require fmri=C
+            add depend type=incorporate fmri=C@%(ver)d
+            close"""
+
+        p_data_template = [
+            p_A_template,
+            p_B_template,
+            p_C_template,
+            p_BB_template,
+            p_BC_template,
+        ]
+        p_data = [p_common]
+        for i in range(4):
+                for j in p_data_template:
+                        p_data.append(j % {"ver": (i + 1)})
+        p_fmri = {}
+
+        def setUp(self):
+                self.i_count = 2
+                pkg5unittest.ManyDepotTestCase.setUp(self, ["test"],
+                    image_count=self.i_count)
+
+                # get repo url
+                self.rurl1 = self.dcs[1].get_repo_url()
+
+                # populate repository
+                for p in self.p_data:
+                        fmristr = self.pkgsend_bulk(self.rurl1, p)[0]
+                        f = fmri.PkgFmri(fmristr, "5.11")
+                        pkgstr = "%s@%s" % (f.pkg_name, f.version.release)
+                        self.p_fmri[pkgstr] = fmristr
+
+                # setup image names and paths
+                self.i_name = []
+                self.i_path = []
+                self.i_api = []
+                self.i_api_reset = []
+                for i in range(self.i_count):
+                        name = "system:img%d" % i
+                        self.i_name.insert(i, name)
+                        self.i_path.insert(i, self.img_path(i))
+
+        def __test_linked_install_hold_relax(self, child_pkgs, op, op_args,
+            op_rv=EXIT_OK, variant_out_parent_dep=False, **kwargs):
+                """Verify that all install-holds get relaxed during
+                sync-linked operations."""
+
+                # create parent (0), and pull child (1)
+                self._imgs_create(2)
+
+                # install B@2 in the parent
+                self._pkg([0], "install -v B@2")
+
+                # install A@1 and B@1 in the child
+                self._pkg([1], "install -v %s" % child_pkgs)
+
+                # the parent dependency only exists under variant.foo=bar, if
+                # we change variant.foo the parent dependency should go away.
+                if variant_out_parent_dep:
+                        self._pkg([1], "change-variant variant.foo=baz")
+
+                # link the two images without syncing packages
+                self._attach_parent([1], 0, args="--linked-md-only")
+
+                if variant_out_parent_dep:
+                        # verify the child is synced
+                        self._pkg([1], "audit-linked", rv=EXIT_OK)
+                else:
+                        # verify the child is diverged
+                        self._pkg([1], "audit-linked", rv=EXIT_DIVERGED)
+
+                # execute op
+                def output_cb(output):
+                        if op_rv == EXIT_OK:
+                                self.assertEqualParsable(output, **kwargs)
+                self._pkg([1], "%s --parsable=0 %s" % (op, op_args),
+                    rv=op_rv, output_cb=output_cb)
+
+        def test_linked_install_hold_relax_all(self):
+                """Verify that all install-holds get relaxed during
+                sync-linked operations."""
+
+                # verify that sync-linked operation relaxes the install-hold
+                # in B and syncs it.
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1", "sync-linked", "",
+                    change_packages=[
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+                # if we remove the parent dependency in B it should no longer
+                # change during sync-linked operation.
+                self.__test_linked_install_hold_relax(
+                    "BC@1", "sync-linked", "", op_rv=EXIT_NOP,
+                    variant_out_parent_dep=True)
+
+        def test_linked_install_hold_relax_constrained_1(self):
+                """Verify that any install-holds which are associated with
+                constrained packages (ie, packages with parent dependencies)
+                get relaxed during install, uninstall and similar
+                operations.
+
+                In our child image we'll install 3 packages, A, B, C, all at
+                version 1.  pkg A, B, and C, all have install holds.  pkg B
+                has a parent dependency and is out of sync.
+
+                We will modify the child image without touching pkg B directly
+                and then verify that the install hold in B gets relaxed, there
+                by allowing the image to be synced."""
+
+                # verify install
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1", "install", "A@2",
+                    change_packages=[
+                        [self.p_fmri["A@1"], self.p_fmri["A@2"]],
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+                # verify update pkg
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1", "update", "A@2",
+                    change_packages=[
+                        [self.p_fmri["A@1"], self.p_fmri["A@2"]],
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+                # verify uninstall
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1", "uninstall", "A@1",
+                    remove_packages=[
+                        self.p_fmri["A@1"]],
+                    change_packages=[
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+                # verify change-variant
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1", "change-variant", "variant.haha=hoho",
+                    change_variants=[
+                        ['variant.haha', 'hoho']],
+                    change_packages=[
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+                # verify change-facet
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1", "change-facet", "facet.haha=False",
+                    change_facets=[
+                        ['facet.haha', False, None, 'local', False, False]],
+                    change_packages=[
+                        [self.p_fmri["B@1"], self.p_fmri["B@2"]]])
+
+        def test_linked_install_hold_relax_constrained_2(self):
+                """Verify that any install-holds which are not associated with
+                constrained packages (ie, packages with parent dependencies)
+                don't get relaxed during install, uninstall and similar
+                operations.
+
+                In our child image we'll install 4 packages, A, B, C, and BC,
+                all at version 1.  pkg A, B, and C, all have install holds.
+                pkg B has a parent dependency and is out of sync.  pkg BC
+                incorporates B and C and links their versions together.
+
+                The child image is out of sync. we should be able to
+                manipulate it, but we won't be able to bring it in sync
+                because of the install hold in C."""
+
+                # verify install
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "install", "A@2",
+                    change_packages=[
+                        [self.p_fmri["A@1"], self.p_fmri["A@2"]]])
+
+                # verify update pkg
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "update", "A@2",
+                    change_packages=[
+                        [self.p_fmri["A@1"], self.p_fmri["A@2"]]])
+
+                # verify uninstall
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "uninstall", "A@1",
+                    remove_packages=[
+                        self.p_fmri["A@1"]])
+
+                # verify change-variant
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "change-variant", "variant.haha=hoho",
+                    change_variants=[
+                        ['variant.haha', 'hoho']])
+
+                # verify change-facet
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "change-facet", "facet.haha=False",
+                    change_facets=[
+                        ['facet.haha', False, None, 'local', False, False]])
+
+        def test_linked_install_hold_relax_constrained_3(self):
+                """Verify that any install-holds which are not associated with
+                constrained packages (ie, packages with parent dependencies)
+                don't get relaxed during install, uninstall and similar
+                operations.
+
+                In our child image we'll install 4 packages, A, B, C, and BC,
+                all at version 1.  pkg A, B, and C, all have install holds.
+                pkg B has a parent dependency and is out of sync.  pkg BC
+                incorporates B and C and links their versions together.
+
+                We'll try to update BC, which should fail because of the
+                install hold in C."""
+
+                # verify install
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "install", "BC@2", op_rv=EXIT_OOPS)
+
+                # verify update pkg
+                self.__test_linked_install_hold_relax(
+                    "A@1 B@1 C@1 BC@1", "update", "BC@2", op_rv=EXIT_OOPS)
+
+        def test_linked_install_hold_relax_constrained_4(self):
+                """Verify that any install-holds which are not associated with
+                constrained packages (ie, packages with parent dependencies)
+                don't get relaxed during install, uninstall and similar
+                operations.
+
+                In our child image we'll install 1 package, B@1.  pkg B has an
+                install hold and a parent dependency, but its parent
+                dependency is disabled by a variant, so the image is in sync.
+
+                We'll try to install package BC@2, which should fail because
+                of the install hold in B."""
+
+                # verify install
+                self.__test_linked_install_hold_relax(
+                    "B@1", "install", "BC@2", op_rv=EXIT_OOPS,
+                    variant_out_parent_dep=True)
+
+
+class TestPkgLinkedScale(pkg5unittest.ManyDepotTestCase):
+        """Test the scalability of the linked image subsystem."""
+
+        max_image_count = 256
+
+        p_sync1 = []
+        p_vers = [
+            "@1.2,5.11-145:19700101T000001Z",
+            "@1.2,5.11-145:19700101T000000Z", # old time
+            "@1.1,5.11-145:19700101T000000Z", # old ver
+            "@1.1,5.11-144:19700101T000000Z", # old build
+            "@1.0,5.11-144:19700101T000000Z", # oldest
+        ]
+        p_files = [
+            "tmp/bar",
+            "tmp/baz",
+        ]
+
+        # generate packages that do need to be synced
+        p_sync1_name_gen = "sync1"
+        pkgs = [p_sync1_name_gen + ver for ver in p_vers]
+        p_sync1_name = dict(zip(range(len(pkgs)), pkgs))
+        for i in p_sync1_name:
+                p_data = "open %s\n" % p_sync1_name[i]
+                p_data += "add depend type=parent fmri=%s" % \
+                    pkg.actions.depend.DEPEND_SELF
+                p_data += """
+                    close\n"""
+                p_sync1.append(p_data)
+
+        def setUp(self):
+                pkg5unittest.ManyDepotTestCase.setUp(self, ["test"],
+                    image_count=self.max_image_count)
+
+                # create files that go in packages
+                self.make_misc_files(self.p_files)
+
+                # get repo url
+                self.rurl1 = self.dcs[1].get_repo_url()
+
+                # populate repository
+                self.pkgsend_bulk(self.rurl1, self.p_sync1)
+
+
+        def __req_phys_mem(self, phys_mem_req):
+                """Verify that the current machine has a minimal amount of
+                physical memory (in GB).  If it doesn't raise
+                TestSkippedException."""
+
+                psize = os.sysconf(os.sysconf_names["SC_PAGESIZE"])
+                ppages = os.sysconf(os.sysconf_names["SC_PHYS_PAGES"])
+                phys_mem = psize * ppages / 1024.0 / 1024.0 / 1024.0
+
+                if phys_mem < phys_mem_req:
+                        raise pkg5unittest.TestSkippedException(
+                            "Not enough memory, "\
+                            "%d GB required, %d GB detected.\n" %
+                            (phys_mem_req, phys_mem))
+
+        def pkg(self, *args, **kwargs):
+                """This is a wrapper function to disable coverage for all
+                tests in this class since these are essentially stress tests.
+                we don't need the coverage data (since other functional tests
+                should have already covered these code paths) and we don't
+                want the added overhead of gathering coverage data (since we
+                want to use all available resource for actually running the
+                tests)."""
+
+                kwargs["coverage"] = False
+                return pkg5unittest.ManyDepotTestCase.pkg(self, *args,
+                    **kwargs);
+
+        def test_li_scale(self):
+                """Verify that we can operate on a large number of linked
+                images in parallel.
+
+                For parallel linked image operations, 256 images is high
+                enough to cause file descriptor allocation to exceed
+                FD_SETSIZE, which in turn can cause select.select() to fail if
+                it's invoked.  In practice that's the only failure mode we've
+                ever seen when people have tried to update a large number of
+                zones in parallel.
+
+                The maximum value successfully tested here has been 512.  I
+                tried 1024 but it resulted in death by swapping on a u27 with
+                12 GB of memory."""
+
+                # we will require at least 11 GB of memory to run this test.
+                # This is a rough estimate of required memory based on
+                # observing this test running on s12_20 on an x86 machine.  on
+                # that machine i observed the peak RSS for pkg child process
+                # was about 24 MB.  with 256 child processes this comes out to
+                # about 6 GB of memory.  we require 11 GB so that the machine
+                # doesn't get bogged down and other things can continue to
+                # run.
+                self.__req_phys_mem(11)
+
+                limit = self.max_image_count
+
+                # create an image with a synced package
+                self.set_image(0)
+                self.image_create(repourl=self.rurl1)
+                self.pkg("install -v %s" % self.p_sync1_name[1])
+
+                # create copies of the image.
+                for i in range(1, self.max_image_count):
+                        self.image_clone(i)
+
+                # attach the copies as children of the original image
+                for i in range(1, self.max_image_count):
+                        name = "system:img%d" % i
+                        cmd = "attach-linked --linked-md-only -c %s %s" % (
+                            name, self.img_path(i))
+                        self.pkg(cmd)
+
+                # update the parent image and all child images in parallel
+                self.pkg("update -C0 -q")
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_list.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_list.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -71,6 +71,15 @@
             open hier/[email protected],5.11-0
             close """
 
+        def __check_qoutput(self, errout=False):
+                self.assertEqualDiff(self.output, "")
+                if errout:
+                        self.assert_(self.errout != "",
+                            "-q must print fatal errors!")
+                else:
+                        self.assert_(self.errout == "",
+                            "-q should only print fatal errors!")
+
         def setUp(self):
                 pkg5unittest.ManyDepotTestCase.setUp(self, ["test1", "test2",
                     "test2"])
@@ -108,6 +117,10 @@
                 self.pkg("list -a -u", exit=2)
                 self.pkg("list -g pkg://test1/ -u", exit=2)
 
+                # Should only print fatal errors when using -q.
+                self.pkg("list -q -v", exit=2)
+                self.__check_qoutput(errout=True)
+
         def test_00(self):
                 """Verify that sort order and content of a full list matches
                 expected."""
@@ -123,6 +136,10 @@
                 output = self.reduceSpaces(self.output)
                 self.assertEqualDiff(expected, output)
 
+                # Should only print fatal errors when using -q.
+                self.pkg("list -aqH")
+                self.__check_qoutput(errout=False)
+
                 self.pkg("list -afH")
                 expected = \
                     ("foo 1.2.1-0 ---\n"
@@ -294,6 +311,12 @@
                 # Install a package from the second publisher.
                 self.pkg("install pkg://test2/[email protected]")
 
+                # Should only print fatal errors when using -q.
+                self.pkg("list -q foo")
+                self.__check_qoutput(errout=False)
+                self.pkg("list -q foo bogus", exit=3)
+                self.__check_qoutput(errout=False)
+
                 # Change the origin of the publisher of an installed package to
                 # that of an empty repository.  The package should still be
                 # shown for test1 and installed for test2.
@@ -338,6 +361,9 @@
                 # privileged user since it hasn't been published yet.
                 self.pkg("list -a | grep newpkg", su_wrap=True, exit=1)
                 self.pkg("list -a | grep newpkg", exit=1)
+                # Should only print fatal errors when using -q.
+                self.pkg("list -aq newpkg", exit=1)
+                self.__check_qoutput(errout=False)
 
                 self.pkgsend_bulk(self.rurl1, self.newpkg10)
 
@@ -369,6 +395,9 @@
                 # Package should now exist for unprivileged user since the
                 # metadata has been refreshed.
                 self.pkg("list -a | grep newpkg", su_wrap=True)
+                # Should only print fatal errors when using -q.
+                self.pkg("list -aq newpkg")
+                self.__check_qoutput(errout=False)
 
         def test_10_all_known_failed_refresh(self):
                 """Verify that a failed implicit refresh will not prevent pkg
@@ -385,6 +414,9 @@
                 # Verify pkg list -a fails for a privileged user when a
                 # publisher's repository is unreachable.
                 self.pkg("list -a", exit=1)
+                # Should only print fatal errors when using -q.
+                self.pkg("list -aq newpkg", exit=1)
+                self.__check_qoutput(errout=True)
 
                 # Reset test2's origin.
                 self.pkg("set-publisher -O %s test2" % self.rurl2)
@@ -404,10 +436,13 @@
 
                 # This should work for an unprivileged user, even though it
                 # requires manifest retrieval (because of the v0 repo).
-                self.pkg("list -a", su_wrap=True)
+
+                # we have to disable mandatory validation because v0 has
+                # no catalog checksums.
+                self.pkg("-D manifest_validate=Never list -a", su_wrap=True)
 
                 # This should work for a privileged user.
-                self.pkg("list -a")
+                self.pkg("-D manifest_validate=Never list -a")
 
                 dc.stop()
                 dc.unset_disable_ops()
@@ -520,12 +555,16 @@
                 # parsing has parsed the option too.)
                 self.pkg("list -a bar@a", exit=1)
                 self.assert_(self.output.find("FMRI '-a'") == -1)
+                # Should only print fatal errors when using -q.
+                self.pkg("list -aq bar@a", exit=1)
+                self.__check_qoutput(errout=True)
 
                 # Last, test all at once.
                 self.pkg("list %s" % " ".join(pats), exit=1)
 
         def test_15_latest(self):
-                """Verify that FMRIs using @latest work as expected."""
+                """Verify that FMRIs using @latest work as expected and
+                that -n provides the same results."""
 
                 self.pkg("list -aHf foo@latest")
                 expected = \
@@ -537,6 +576,11 @@
                 expected = self.reduceSpaces(expected)
                 self.assertEqualDiff(expected, output)
 
+                self.pkg("list -Hn foo")
+                output = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected)
+                self.assertEqualDiff(expected, output)
+
                 self.pkg("list -aHf foo@latest [email protected] //test2/[email protected]")
                 expected = \
                     "foo              1.2.1-0 ---\n" \
@@ -559,6 +603,46 @@
                 expected = self.reduceSpaces(expected)
                 self.assertEqualDiff(expected, output)
 
+                self.pkg("list -Hn /hier/foo //test1/foo")
+                output = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected)
+                self.assertEqualDiff(expected, output)
+
+        def test_16_upgradable(self):
+                """Verify that pkg list -u works as expected."""
+
+                self.image_create(self.rurl1)
+                self.pkg("install /[email protected]")
+
+                # 'foo' should be listed since 1.2.1 is available.
+                self.pkg("list -H")
+                expected = \
+                    "foo              1.0-0 i--\n"
+                output = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected)
+                self.assertEqualDiff(expected, output)
+
+                # 'foo' should be listed since 1.2.1 is available.
+                self.pkg("list -Hu foo")
+                output = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected)
+                self.assertEqualDiff(expected, output)
+
+                # Should not print anything if using -q.
+                self.pkg("list -Hqu foo")
+                self.__check_qoutput(errout=False)
+
+                # Upgrade foo.
+                self.pkg("update foo")
+
+                # Should return error as newest version is now installed.
+                self.pkg("list -Hu foo", exit=1)
+                self.assertEqualDiff(self.output, "")
+                self.assert_(self.errout != "")
+                # Should not print anything if using -q.
+                self.pkg("list -Hqu foo", exit=1)
+                self.__check_qoutput(errout=False)
+
 
 class TestPkgListSingle(pkg5unittest.SingleDepotTestCase):
         # Destroy test space every time.
@@ -573,12 +657,25 @@
             add depend type=require [email protected]
             close """
 
+        def __check_qoutput(self, errout=False):
+                self.assertEqualDiff(self.output, "")
+                if errout:
+                        self.assert_(self.errout != "",
+                            "-q must print fatal errors!")
+                else:
+                        self.assert_(self.errout == "",
+                            "-q should only print fatal errors!")
+
         def test_01_empty_image(self):
                 """ pkg list should fail in an empty image """
 
                 self.image_create(self.rurl)
                 self.pkg("list", exit=1)
 
+                # Should not print anything if using -q.
+                self.pkg("list -q", exit=1)
+                self.__check_qoutput(errout=False)
+
         def __populate_repo(self, unsupp_content):
                 # Publish a package and then add some unsupported action data
                 # to the repository's copy of the manifest and catalog.
@@ -636,6 +733,9 @@
                 expected = self.reduceSpaces(expected)
                 self.assertEqualDiff(expected, output)
 
+                self.pkg("list -qaH foo unsupported")
+                self.__check_qoutput(errout=False)
+
                 # Verify that a package with invalid content doesn't cause
                 # a problem.
                 newact = "depend notvalid"
@@ -650,6 +750,9 @@
                 expected = self.reduceSpaces(expected)
                 self.assertEqualDiff(expected, output)
 
+                self.pkg("list -afqH foo unsupported")
+                self.__check_qoutput(errout=False)
+
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_mediated.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_mediated.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -44,6 +44,13 @@
         persistent_setup = True
 
         pkg_sendmail = """
+            open pkg://test/[email protected]
+            add set name=pkg.summary value="Example sendmail package"
+            add file tmp/foosm path=/usr/bin/mailq owner=root group=root mode=0555
+            add file tmp/foosm path=/usr/lib/sendmail owner=root group=root mode=2555
+            add link path=/usr/sbin/newaliases target=../lib/sendmail
+            add link path=/usr/sbin/sendmail target=../lib/sendmail
+            close
             open pkg://test/[email protected]
             add set name=pkg.summary value="Example sendmail package"
             add file tmp/foosm path=/usr/lib/sendmail-mta/sendmail owner=root group=root mode=2555
@@ -61,6 +68,15 @@
             add link path=/usr/lib/sendmail target=../lib/sendmail-mta/sendmail mediator=mta mediator-implementation=sendmail mediator-priority=vendor
             add link path=/usr/sbin/newaliases target=../lib/sendmail-mta/sendmail mediator=mta mediator-implementation=sendmail mediator-priority=vendor
             add link path=/usr/sbin/sendmail target=../lib/sendmail-mta/sendmail mediator=mta mediator-implementation=sendmail mediator-priority=vendor
+            close
+            open pkg://test/[email protected]
+            add set name=pkg.summary value="Example sendmail target change package"
+            add file tmp/foosm path=/usr/lib/sendmail3-mta/sendmail owner=root group=root mode=2555
+            add file tmp/foosm path=/usr/lib/sendmail3-mta/mailq owner=root group=root mode=0555
+            add link path=/usr/bin/mailq target=../lib/sendmail3-mta/mailq3 mediator=mta mediator-implementation=sendmail
+            add link path=/usr/lib/sendmail target=../lib/sendmail3-mta/sendmail mediator=mta mediator-implementation=sendmail
+            add link path=/usr/sbin/newaliases target=../lib/sendmail3-mta/sendmail mediator=mta mediator-implementation=sendmail
+            add link path=/usr/sbin/sendmail target=../lib/sendmail3-mta/sendmail mediator=mta mediator-implementation=sendmail
             close """
 
         pkg_sendmail_links = """
@@ -185,6 +201,27 @@
             add link path=/usr/bin/python target=python2.8-unladen-swallow mediator=python mediator-version=2.8 [email protected]
             close """
 
+        pkg_multi_python = """
+            open pkg://test/runtime/[email protected]
+            add set name=pkg.summary value="Example python package with multiple implementations"
+            add file tmp/foopy path=/usr/bin/python2.6 owner=root group=bin mode=0555
+            add link path=/usr/bin/python target=python2.6 mediator=python mediator-implementation=cpython
+            add file tmp/foopyus path=/usr/bin/python2.6-unladen-swallow owner=root group=bin mode=0555
+            add link path=/usr/bin/python target=python2.6-unladen-swallow mediator=python mediator-implementation=unladen-swallow
+            close
+            open pkg://test/runtime/[email protected]
+            add set name=pkg.summary value="Example python implementation package with multiple implementations and versions"
+            add file tmp/foopy path=/usr/bin/python2.6 owner=root group=bin mode=0555
+            add link path=/usr/bin/python target=python2.6 mediator=python mediator-version=2.6
+            add file tmp/foopyus path=/usr/bin/python2.6-unladen-swallow owner=root group=bin mode=0555
+            add file tmp/foopy path=/usr/bin/python2.7 owner=root group=bin mode=0555
+            add link path=/usr/bin/python target=python2.7 mediator=python mediator-version=2.7
+            add link path=/usr/bin/python target=python2.6-unladen-swallow mediator=python mediator-version=2.6 mediator-implementation=unladen-swallow
+            add file tmp/foopyus path=/usr/bin/python2.7-unladen-swallow owner=root group=bin mode=0555
+            add link path=/usr/bin/python target=python2.7-unladen-swallow mediator=python mediator-version=2.7 mediator-implementation=unladen-swallow
+            close
+            """
+
         pkg_vi = """
             open pkg://test/editor/[email protected]
             add set name=pkg.summary value="Example nvi vendor priority package"
@@ -207,6 +244,28 @@
             add hardlink path=/usr/bin/vi target=vim mediator=vi mediator-implementation=vim mediator-priority=site facet.vi=true
             close """
 
+        pkg_multi_ver = """
+            open pkg://test/web/server/apache-22/module/[email protected]
+            add set name=pkg.summary value="Example multiple version mod_php package"
+            add file tmp/fooc path=usr/apache2/2.2/libexec/mod_php5.2.so owner=root group=bin mode=0555
+            add link path=usr/apache2/2.2/libexec/mod_php5.so target=mod_php5.2.so mediator=php mediator-version=5.2
+            add file tmp/food path=usr/apache2/2.2/libexec/mod_php5.2.5.so owner=root group=bin mode=0555
+            add link path=usr/apache2/2.2/libexec/mod_php5.so target=mod_php5.2.5.so mediator=php mediator-version=5.2.5
+            close """
+
+        pkg_variant = """
+            open pkg://test/[email protected]
+            add set name=pkg.summary value="Example mediated varianted package"
+            add file tmp/fooc path=/usr/bin/foo-1-nd owner=root group=bin mode=0555
+            add file tmp/food path=/usr/bin/foo-1-d owner=root group=bin mode=0555
+            add hardlink path=usr/bin/foo target=foo-1-nd mediator=foo mediator-version=1 variant.debug.osnet=false
+            add hardlink path=usr/bin/foo target=foo-1-d mediator=foo mediator-version=1 variant.debug.osnet=true
+            add file tmp/fooc path=/usr/bin/foo-2-nd owner=root group=bin mode=0555
+            add file tmp/food path=/usr/bin/foo-2-d owner=root group=bin mode=0555
+            add hardlink path=usr/bin/foo target=foo-2-nd mediator=foo mediator-version=2 variant.debug.osnet=false
+            add hardlink path=usr/bin/foo target=foo-2-d mediator=foo mediator-version=2 variant.debug.osnet=true
+            close """
+
         misc_files = ["tmp/fooc", "tmp/food", "tmp/foopl", "tmp/foopy",
             "tmp/foopyus", "tmp/foosm", "tmp/foopf", "tmp/foou", "tmp/foonvi",
             "tmp/foovi", "tmp/foovim"]
@@ -340,7 +399,7 @@
 
                 # Now install some packages to test the ability to list
                 # available mediations.
-                self.pkg("install -vvv \*python\* \*perl\* \*vi\*")
+                self.pkg("install -vvv \*/python\* \*perl\* \*vi\*")
 
                 # Test listing all available mediations.
                 self.__assert_available_mediation_matches("""\
@@ -410,6 +469,17 @@
 
                 self.image_create(self.rurl)
 
+                def gen_mta_files():
+                        for fname in ("mailq",):
+                                fpath = os.path.join(self.img_path(), "usr",
+                                    "bin", fname)
+                                yield fpath
+
+                        for fname in ("sendmail",):
+                                fpath = os.path.join(self.img_path(), "usr",
+                                    "lib", fname)
+                                yield fpath
+
                 def gen_mta_links():
                         for lname in ("mailq",):
                                 lpath = os.path.join(self.img_path(), "usr",
@@ -432,12 +502,23 @@
                                     "bin", lname)
                                 yield lpath
 
+                def gen_php_links():
+                        for lname in ("mod_php5.so",):
+                                lpath = os.path.join(self.img_path(), "usr",
+                                    "apache2", "2.2", "libexec", lname)
+                                yield lpath
+
                 def gen_python_links():
                         for lname in ("python",):
                                 lpath = os.path.join(self.img_path(), "usr",
                                     "bin", lname)
                                 yield lpath
 
+                def check_files(files):
+                        for fpath in files:
+                                s = os.lstat(fpath)
+                                self.assert_(stat.S_ISREG(s.st_mode))
+
                 def check_target(links, target):
                         for lpath in links:
                                 ltarget = os.readlink(lpath)
@@ -462,8 +543,17 @@
 
                 # Some installs are done with extra verbosity to ease in
                 # debugging tests when they fail.
+                self.pkg("install -vvv [email protected]")
+                self.pkg("mediator") # If tests fail, this is helpful.
+
+                # Verify that /usr/bin/mailq and /usr/lib/sendmail are files.
+                check_files(gen_mta_files())
+                self.pkg("verify -v")
+
+                # Upgrading to 1.0 should transition the files to links.
                 self.pkg("install -vvv sendmail@1")
                 self.pkg("mediator") # If tests fail, this is helpful.
+                self.pkg("verify -v")
 
                 # Check that installed links point to sendmail and that
                 # verify passes.
@@ -473,6 +563,25 @@
 mta\tsystem\t\tsystem\tsendmail\t
 """)
 
+                # Upgrading to 3.0 should change the targets of every link.
+                self.pkg("install -vvv sendmail@3")
+                self.pkg("mediator") # If tests fail, this is helpful.
+                check_target(gen_mta_links(), "sendmail3-mta")
+                self.pkg("verify -v")
+
+                # Downgrading to 0.5 should change sendmail and mailq links back
+                # to a file.
+                self.pkg("update -vvv [email protected]")
+                self.pkg("mediator") # If tests fail, this is helpful.
+                check_files(gen_mta_files())
+                self.pkg("verify -v")
+
+                # Finally, upgrade to 1.0 again for remaining tests.
+                self.pkg("update -vvv [email protected]")
+                self.pkg("mediator") # If tests fail, this is helpful.
+                check_target(gen_mta_links(), "sendmail-mta")
+                self.pkg("verify -v")
+
                 # Install postfix (this should succeed even though sendmail is
                 # already installed) and the links should be updated to point to
                 # postfix, and verify should pass.
@@ -886,6 +995,88 @@
                 self.pkg("fix")
                 self.pkg("verify -v")
 
+                # Remove all packages; then verify that installing a single
+                # package that has multiple version mediations works as
+                # expected.
+                self.pkg("unset-mediator -I python")
+                self.pkg("uninstall \*")
+
+                # Install apache-php52; verify that php 5.2.5 is selected.
+                self.pkg("install -vvv apache-php52")
+                self.__assert_mediation_matches("""\
+php\tsystem\t5.2.5\tsystem\t\t
+""")
+                check_target(gen_php_links(), "5.2.5")
+                self.pkg("verify")
+
+                # Test available mediations.
+                self.__assert_available_mediation_matches("""\
+php\tsystem\t5.2.5\tsystem\t\t
+php\tsystem\t5.2\tsystem\t\t
+""")
+
+                # Set mediation version to 5.2 and verify 5.2.5 is NOT selected.
+                self.pkg("set-mediator -vvv -V 5.2 php")
+                self.__assert_mediation_matches("""\
+php\tlocal\t5.2\tsystem\t\t
+""")
+                check_not_target(gen_php_links(), "5.2.5")
+                self.pkg("verify")
+
+                # Remove all packages; then verify that installing a single
+                # package that has multiple mediation implementations works as
+                # expected.
+                self.pkg("uninstall \*")
+                self.pkg("unset-mediator -V php")
+
+                # Install multi-impl-python; verify that unladen swallow is NOT
+                # selected.
+                self.pkg("install -vvv multi-impl-python-26")
+                self.__assert_mediation_matches("""\
+python\tsystem\t\tsystem\tcpython\t
+""")
+                check_not_target(gen_python_links(), "unladen-swallow")
+                self.pkg("verify")
+
+                # Test available mediations.
+                self.__assert_available_mediation_matches("""\
+python\tsystem\t\tsystem\tcpython\t
+python\tsystem\t\tsystem\tunladen-swallow\t
+""")
+
+                # Set mediation implementation to unladen swallow and verify it
+                # was selected.
+                self.pkg("set-mediator -vvv -I unladen-swallow python")
+                self.__assert_mediation_matches("""\
+python\tsystem\t\tlocal\tunladen-swallow\t
+""")
+                check_target(gen_python_links(), "unladen-swallow")
+                self.pkg("verify")
+
+                # Remove all packages; then verify that installing a single
+                # package that has multiple mediation and version
+                # implementations works as expected.
+                self.pkg("uninstall \*")
+                self.pkg("unset-mediator -I python")
+                self.pkg("install -vvv multi-impl-ver-python")
+
+                # Verify that the default implementation of Python 2.7 was
+                # selected even though the package offers Python 2.6 and an
+                # unladen swallow implemenation of each version of Python.
+                self.__assert_mediation_matches("""\
+python\tsystem\t2.7\tsystem\t\t
+""")
+                check_not_target(gen_python_links(), "unladen-swallow")
+                self.pkg("verify")
+
+                # Test available mediations.
+                self.__assert_available_mediation_matches("""\
+python\tsystem\t2.7\tsystem\t\t
+python\tsystem\t2.7\tsystem\tunladen-swallow\t
+python\tsystem\t2.6\tsystem\t\t
+python\tsystem\t2.6\tsystem\tunladen-swallow\t
+""")
+
         def test_02_hardlink_mediation(self):
                 """Verify that package mediation works as expected for install,
                 update, and uninstall with hardlinks.
@@ -989,6 +1180,52 @@
 vi\tsite\t\tsite\tvim\t
 """)
 
+                # Uninstall all packages; then verify that a single package
+                # containing multiple varianted, mediated hardlinks works as
+                # expected.
+                self.pkg("uninstall \*")
+
+                foo_path = get_link_path("usr", "bin", "foo")
+                foo_1_nd_path = get_link_path("usr", "bin", "foo-1-nd")
+                foo_1_d_path = get_link_path("usr", "bin", "foo-1-d")
+                foo_2_nd_path = get_link_path("usr", "bin", "foo-2-nd")
+                foo_2_d_path = get_link_path("usr", "bin", "foo-2-d")
+
+                # Install multi-ver-variant and verify version 2 non-debug is
+                # selected.
+                self.pkg("install -vvv multi-ver-variant")
+                assert_target(foo_path, foo_2_nd_path)
+                self.__assert_mediation_matches("""\
+foo\tsystem\t2\tsystem\t\t
+""")
+                self.pkg("verify")
+
+                # Set debug variant and verify version 2 debug is selected.
+                self.pkg("change-variant -vvv debug.osnet=true")
+                assert_target(foo_path, foo_2_d_path)
+                self.__assert_mediation_matches("""\
+foo\tsystem\t2\tsystem\t\t
+""")
+                self.pkg("verify")
+
+                # Set mediator version to 1 and verify version 1 debug is
+                # selected.
+                self.pkg("set-mediator -vvv -V 1 foo")
+                assert_target(foo_path, foo_1_d_path)
+                self.__assert_mediation_matches("""\
+foo\tlocal\t1\tsystem\t\t
+""")
+                self.pkg("verify")
+
+                # Reset debug variant and verify version 1 non-debug is
+                # selected.
+                self.pkg("change-variant -vvv debug.osnet=false")
+                self.pkg("verify")
+                assert_target(foo_path, foo_1_nd_path)
+                self.__assert_mediation_matches("""\
+foo\tlocal\t1\tsystem\t\t
+""")
+
 
 if __name__ == "__main__":
         unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_pkg_nasty.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,355 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+import pkg5unittest
+
+import os
+import unittest
+import random
+import re
+import shutil
+
+class TestPkgNasty(pkg5unittest.SingleDepotTestCase):
+
+        need_ro_data = True
+
+        # Default number iterations; tune with NASTY_ITERS in environ.
+        NASTY_ITERS = 10
+        # Default nastiness; tune with NASTY_LEVEL in environ.
+        NASTY_LEVEL = 50
+
+        NASTY_SLEEP = 2
+
+        template_10 = """
+            open testpkg/[email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/stuff
+            add file tmp/file1 mode=0644 owner=root group=bin path=/__SUB__/f1 preserve=true
+            add file tmp/file2 mode=0644 owner=root group=bin path=/__SUB__/f2
+            add file tmp/file3 mode=0644 owner=root group=bin path=/__SUB__/f3
+            close """
+
+        # in v1.1, file contents are shifted around
+        template_11 = """
+            open testpkg/[email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/stuff
+            add file tmp/file2 mode=0644 owner=root group=bin path=/__SUB__/f1 preserve=true
+            add file tmp/file3 mode=0644 owner=root group=bin path=/__SUB__/f2
+            add file tmp/file4 mode=0644 owner=root group=bin path=/__SUB__/f3
+            add file tmp/file5 mode=0644 owner=root group=bin path=/__SUB__/f4
+            close """
+
+        def __make_rand_string(self, outlen):
+                s = ""
+                while outlen > 0:
+                        s += random.choice("\n\n\n\nabcdefghijklmnopqrstuvwxyz"
+                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()")
+                        outlen -= 1
+                return s
+
+        def __make_rand_files(self):
+                misc_files = {
+                    "tmp/file1": 1,
+                    "tmp/file2": 32,
+                    "tmp/file3": 4096,
+                    "tmp/file4": 16384,
+                    "tmp/file5": 65536
+                }
+                for f in misc_files:
+                        # Overwrite the number with file contents of size
+                        # <that number>
+                        misc_files[f] = \
+                            self.__make_rand_string(misc_files[f])
+                self.make_misc_files(misc_files)
+
+        def __make_pkgs(self):
+                self.testpkgs = []
+                for pkgname in ["A", "B", "C", "D"]:
+                        self.testpkgs.append(re.sub("__SUB__", pkgname,
+                            self.template_10))
+                        self.testpkgs.append(re.sub("__SUB__", pkgname,
+                            self.template_11))
+
+        def setUp(self):
+                pkg5unittest.SingleDepotTestCase.setUp(self)
+
+                self.NASTY_ITERS = \
+                    int(os.environ.get("NASTY_ITERS", self.NASTY_ITERS))
+                self.NASTY_LEVEL = \
+                    int(os.environ.get("NASTY_LEVEL", self.NASTY_LEVEL))
+
+                os.chdir(self.test_root)
+                self.__make_rand_files()
+                self.__make_pkgs()
+                for pkgcontents in self.testpkgs:
+                        plist = self.pkgsend_bulk(self.rurl, pkgcontents)
+                        self.pkgsign_simple(self.rurl, plist[0])
+                self.dc.set_nasty(self.NASTY_LEVEL)
+                self.dc.set_nasty_sleep(self.NASTY_SLEEP)
+
+                self.nasty_env = {
+                    "PKG_CLIENT_MAX_CONSECUTIVE_ERRORS": "3",
+                    "PKG_CLIENT_MAX_TIMEOUT": "2",
+                    "PKG_CLIENT_LOWSPEED_TIMEOUT": \
+                        "%d" % (self.NASTY_SLEEP - 1),
+                }
+
+                self.dc.start()
+
+                pubname = "test"
+                self.mfst_path = os.path.join(self.img_path(),
+                    "var/pkg/publisher/%s/pkg" % pubname)
+
+        def _rm_mfsts(self):
+                # Note that we have chosen not to ignore errors here,
+                # since we're depending on knowing the internal layout
+                # of var/pkg.
+                shutil.rmtree(self.mfst_path)
+
+        def _dumplog(self):
+                self.debug("---- Last 50 depot log entries:")
+                try:
+                        lp = self.dc.get_logpath()
+                        log = open(lp)
+                        lines = log.readlines()
+                        self.debug("".join(lines[-50:]))
+                except StandardError:
+                        self.debug("Failed to print log entries")
+
+        def _trythis(self, label, kallable, ntries=10):
+                """Runs kallable ntries times; if after ntries the operation
+                has not returned 0, try again with the nastiness disabled in
+                the depot.  The goal is to push through to get a real result
+                but also to prevent infinite looping."""
+                for tries in range(1, ntries + 1):
+                        if tries > 1:
+                                self.debug(
+                                    "--try: '%s' try #%d" %
+                                    (label, tries))
+                        ret = kallable()
+                        if ret == 0:
+                                break
+                else:
+                        # Turn nastiness off on the depot and try again;
+                        # this helps prevent waiting around forever for
+                        # something to eventually work.
+                        self.debug("Note: Repeated failures for '%s' "
+                            "(%d times).  Disabling nasty and retrying" %
+                            (label, ntries))
+                        # Reset environment params and depot nastiness.
+                        # We have to edit self.nasty_env in place (as opposed
+                        # to just replacing it) because a reference to it is
+                        # already bound up with kallable.
+                        save_low = self.nasty_env["PKG_CLIENT_LOWSPEED_TIMEOUT"]
+                        save_maxtmo = self.nasty_env["PKG_CLIENT_MAX_TIMEOUT"]
+                        # Set these to "" to make them revert to defaults
+                        self.nasty_env["PKG_CLIENT_LOWSPEED_TIMEOUT"] = ""
+                        self.nasty_env["PKG_CLIENT_MAX_TIMEOUT"] = ""
+                        self.dc.set_nasty(0)
+
+                        ret = kallable()
+
+                        # Restore Nastiness and environment parameters.
+                        self.nasty_env["PKG_CLIENT_LOWSPEED_TIMEOUT"] = save_low
+                        self.nasty_env["PKG_CLIENT_MAX_TIMEOUT"] = save_maxtmo
+                        self.dc.set_nasty(self.NASTY_LEVEL)
+                        if ret != 0:
+                                raise self.failureException(
+                                    "Failed '%s' %d times, then failed again "
+                                    "with nasty disabled.  Test failed" %
+                                    (label, ntries))
+
+        def do_main_loop(self, kallable):
+                """Loop running a nasty test.  Iterations tunable by setting
+                NASTY_ITERS in the process environment, i.e. NASTY_ITERS=100."""
+                for x in range(1, self.NASTY_ITERS + 1):
+                        self.debug("---- Iteration %d/%d ----" %
+                            (x, self.NASTY_ITERS))
+                        try:
+                                kallable()
+                        except:
+                                self._dumplog()
+                                self.debug("---- Iteration %d/%d FAILED ----" %
+                                    (x, self.NASTY_ITERS))
+                                raise
+
+
+class TestNastyInstall(TestPkgNasty):
+        # Exists as a subclass only so we can run tests in parallel.
+
+        def __nasty_install_1_run(self):
+                env = self.nasty_env
+
+                self._trythis("image create",
+                    lambda: self.pkg_image_create(repourl=self.durl,
+                    env_arg=env, exit=[0, 1]))
+
+                # Set up signature stuff.
+                emptyCA = os.path.join(self.img_path(), "emptyCA")
+                os.makedirs(emptyCA)
+                self.pkg("set-property trust-anchor-directory emptyCA")
+                self.seed_ta_dir("ta3", dest_dir=emptyCA)
+                self.pkg("set-property signature-policy require-signatures")
+
+                self._trythis("refresh",
+                    lambda: self.pkg("refresh", env_arg=env, exit=[0, 1]))
+                self._trythis("refresh --full",
+                    lambda: self.pkg("refresh --full",
+                        env_arg=env, exit=[0, 1]))
+                self._trythis("search -r /A/f2",
+                    lambda: self.pkg("search -r /A/f2",
+                        env_arg=env, exit=[0, 1, 3]))
+
+                # test contents -r
+                contentscmd = "contents -m -r testpkg/*[email protected]"
+                self._trythis(contentscmd, 
+                    lambda: self.pkg(contentscmd, env_arg=env, exit=[0, 1]))
+                # clean up mfsts.
+                self._rm_mfsts()
+
+                self._trythis("install testpkg/*@1.0",
+                    lambda: self.pkg("install testpkg/*@1.0",
+                        env_arg=env, exit=[0, 1]))
+                self._trythis("update",
+                    lambda: self.pkg("update", env_arg=env, exit=[0, 1]))
+
+                # Change a file in the image and then revert it.
+                path = os.path.join(self.img_path(), "A", "f1")
+                self.assert_(os.path.exists(path))
+                f = open(path, "w")
+                print >> f, "I LIKE COCONUTS!"
+                f.close()
+                self._trythis("revert",
+                    lambda: self.pkg("revert A/f1", env_arg=env, exit=[0, 1]))
+
+                # Try some things which are supposed to fail; we can't really
+                # pick apart transport failures versus the actual semantic
+                # failure; oh well for now.
+                self.pkg("search -r /doesnotexist", env_arg=env, exit=1)
+                self.pkg("contents -r doesnotexist", env_arg=env, exit=1)
+                self.pkg("verify", exit=0)
+
+        def test_install_nasty_looping(self):
+                """Test the pkg command against a nasty depot."""
+                self.do_main_loop(self.__nasty_install_1_run)
+
+
+class TestNastyPkgUtils(TestPkgNasty):
+        # Exists as a subclass only so we can run tests in parallel.
+        persistent_setup = True
+
+        def __nasty_pkgrecv_1_run(self):
+                env = self.nasty_env
+                self.cmdline_run("rm -rf test_repo", exit=[0, 1],
+                    coverage=False)
+                self.pkgrepo("create test_repo")
+                self._trythis("recv *",
+                    lambda: self.pkgrecv(self.durl,
+                        "-d test_repo '*'", env_arg=env, exit=[0, 1]))
+                # clean up pkgrecv "resume" turds
+                self.cmdline_run("rm -rf pkgrecv-*", exit=[0, 1],
+                    coverage=False)
+
+        def test_pkgrecv_nasty_looping(self):
+                """Test the pkgrecv command against a nasty depot."""
+                self.do_main_loop(self.__nasty_pkgrecv_1_run)
+
+        def __nasty_pkgrepo_1_run(self):
+                env = self.nasty_env
+                self._trythis("pkgrepo get",
+                    lambda: self.pkgrepo(
+                        "get -s %s" % self.durl, env_arg=env, exit=[0, 1]))
+                self._trythis("pkgrepo info",
+                    lambda: self.pkgrepo(
+                        "info -s %s" % self.durl, env_arg=env, exit=[0, 1]))
+                self._trythis("pkgrepo list",
+                    lambda: self.pkgrepo(
+                        "list -s %s" % self.durl, env_arg=env, exit=[0, 1]))
+                self._trythis("pkgrepo rebuild",
+                    lambda: self.pkgrepo(
+                        "rebuild -s %s" % self.durl, env_arg=env, exit=[0, 1]))
+                self._trythis("pkgrepo refresh",
+                    lambda: self.pkgrepo(
+                        "refresh -s %s" % self.durl, env_arg=env, exit=[0, 1]))
+
+        def test_pkgrepo_nasty_looping(self):
+                """Test the pkgrepo command against a nasty depot."""
+                self.do_main_loop(self.__nasty_pkgrepo_1_run)
+
+
+class TestNastyTempPub(TestPkgNasty):
+        # Exists as a subclass only so we can run tests in parallel.
+
+        def __nasty_temppub_1_run(self):
+                env = self.nasty_env
+
+                self.pkg_image_create(repourl=None)
+                # Set up signature stuff.
+                emptyCA = os.path.join(self.img_path(), "emptyCA")
+                os.makedirs(emptyCA)
+                self.pkg("set-property trust-anchor-directory emptyCA")
+                self.seed_ta_dir("ta3", dest_dir=emptyCA)
+                self.pkg("set-property signature-policy require-signatures")
+
+                # test list with temporary publisher
+                cmd = "list -a -g %s \*" % self.durl
+                self._trythis(cmd,
+                    lambda: self.pkg(cmd, env_arg=env, exit=[0, 1]))
+
+                # test contents with temporary publisher
+                cmd = "contents -m -g %s -r testpkg/*[email protected]" % self.durl
+                self._trythis(cmd,
+                    lambda: self.pkg(cmd, env_arg=env, exit=[0, 1]))
+
+                # clean out dl'd mfsts
+                self._rm_mfsts()
+                # test info with temporary publisher
+                cmd = "info -g %s \*" % self.durl
+                self._trythis(cmd,
+                    lambda: self.pkg(cmd, env_arg=env, exit=[0, 1]))
+
+                # clean out dl'd mfsts
+                self._rm_mfsts()
+                # test install with temporary publisher
+                cmd = "install -g %s testpkg/*@1.0" % self.durl
+                self._trythis(cmd,
+                    lambda: self.pkg(cmd, env_arg=env, exit=[0, 1]))
+
+                # test update with temporary publisher
+                cmd = "update -g %s" % self.durl
+                self._trythis(cmd,
+                    lambda: self.pkg(cmd, env_arg=env, exit=[0, 1]))
+
+                self.pkg("verify", exit=0)
+
+        def test_temppub_nasty_looping(self):
+                self.do_main_loop(self.__nasty_temppub_1_run)
+
+
+if __name__ == "__main__":
+        unittest.main()
--- a/src/tests/cli/t_pkg_publisher.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_publisher.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -66,6 +66,7 @@
                 self.pkg("set-publisher -c", exit=2)
                 self.pkg("set-publisher -O", exit=2)
                 self.pkg("unset-publisher", exit=2)
+                self.pkg("unset-publisher -k", exit=2)
 
         def test_publisher_add_remove(self):
                 """pkg: add and remove a publisher"""
@@ -88,15 +89,6 @@
                 self.pkg("unset-publisher test1")
                 self.pkg("publisher | grep test1", exit=1)
 
-                # Verify that compatibility commands for publisher work (only
-                # minimal verification is needed since these commands map
-                # directly to the publisher ones).  All of these are deprecated
-                # and will be removed at a future date.
-                self.pkg("authority test2")
-                self.pkg("set-authority --no-refresh -O http://%s2 test1" %
-                    self.bogus_url)
-                self.pkg("unset-authority test1")
-
                 # Now verify that partial success (3) or complete failure (1)
                 # is properly returned if an attempt to remove one or more
                 # publishers only results in some of them being removed:
@@ -809,13 +801,6 @@
                 self.__update_repo_pub_cfg(self.dcs[6], t6cfg)
                 self.dcs[6].start()
 
-                # Should fail since even though repository publisher prefix
-                # matches test3, the new origin isn't configured for test3,
-                # and as a result isn't a known source for publisher updates.
-                self.pkg("set-publisher -p %s" % durl6, exit=1)
-
-                # So, add the new origin to the publisher.
-                self.pkg("set-publisher -g %s test3" % durl6)
                 self.pkg("set-publisher -p %s" % durl6)
 
                 # Load image configuration to verify publisher was configured
@@ -1135,6 +1120,13 @@
                 self.assertEqual(lines[1].split()[0], "test1")
                 self.assertEqual(lines[2].split()[0], "test2")
 
+        def test_multiple_p_option(self):
+                """Verify that providing multiple repositories using 
+                -p option fails"""
+                self.image_create()
+                self.pkg("set-publisher -p %s -p %s" % (self.rurl1,
+                    self.rurl2), exit=2)
+
 
 class TestPkgPublisherCACerts(pkg5unittest.ManyDepotTestCase):
         # Tests in this suite use the read only data directory.
--- a/src/tests/cli/t_pkg_revert.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_revert.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -32,7 +32,7 @@
 import os
 import pkg.portable as portable
 import pkg.misc as misc
-
+import sys
 
 class TestPkgRevert(pkg5unittest.SingleDepotTestCase):
         # Only start/stop the depot once (instead of for every test)
@@ -70,29 +70,112 @@
             open [email protected],5.11-0
             add dir mode=0755 owner=root group=bin path=etc
             add file etc/file4 mode=0555 owner=root group=bin path=etc/file4 revert-tag=bob revert-tag=ted revert-tag=carol preserve=true
-            close"""
+            close
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=etc revert-tag=bob=*
+            close
+            open [email protected],5.11-0
+            add file etc/file5 mode=0555 owner=root group=bin path=etc/wombat/file1
+            close
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=etc/y-dir revert-tag=bob=*
+            close
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=dev revert-tag=init-dev=*
+            add dir mode=0755 owner=root group=bin path=dev/cfg revert-tag=init-dev=*
+            add file dev/foo path=dev/foo mode=0555 owner=root group=bin
+            add file dev/cfg/bar path=dev/cfg/bar mode=0555 owner=root group=bin
+            add file dev/cfg/blah path=dev/cfg/blah mode=0555 owner=root group=bin
+            close
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=dev revert-tag=init-dev=*
+            add dir mode=0755 owner=root group=bin path=dev/cfg revert-tag=init-dev=*
+            add file dev/cfg/bar1 path=dev/cfg/bar1 mode=0555 owner=root group=bin
+            add file dev/cfg/bar2 path=dev/cfg/bar2 mode=0555 owner=root group=bin preserve=true revert-tag=init-dev
+            close
+            """
 
-        misc_files = ["etc/file1", "etc/file2", "etc/file3", "etc/file4"]
+        misc_files = ["etc/file1", "etc/file2", "etc/file3", "etc/file4",
+		      "etc/file5"]
+
+	additional_files = ["dev/foo", "dev/cfg/bar", "dev/cfg/blah",
+			    "dev/cfg/bar1", "dev/cfg/bar2"]
 
         def damage_all_files(self):
+                self.damage_files(self.misc_files)
+
+        def damage_files(self, paths):
                 ubin = portable.get_user_by_name("bin", None, False)
                 groot = portable.get_group_by_name("root", None, False)
-                for path in self.misc_files:
+                for path in paths:
                         file_path = os.path.join(self.get_img_path(), path)
                         with open(file_path, "a+") as f:
                                 f.write("\nbogus\n")
                         os.chown(file_path, ubin, groot)
                         os.chmod(file_path, misc.PKG_RO_FILE_MODE)
 
+        def create_some_files(self, paths):
+                ubin = portable.get_user_by_name("bin", None, False)
+                groot = portable.get_group_by_name("root", None, False)
+                for p in paths:
+                        if p.startswith(os.path.sep):
+                                p = p[1:]
+                        file_path = os.path.join(self.get_img_path(), p)
+                        dirpath = os.path.dirname(file_path)
+                        if not os.path.exists(dirpath):
+                                os.mkdir(dirpath)
+                        if p.endswith(os.path.sep):
+                                continue
+                        with open(file_path, "a+") as f:
+                                f.write("\ncontents\n")
+                        os.chown(file_path, ubin, groot)
+                        os.chmod(file_path, misc.PKG_RO_FILE_MODE)
+
+        def files_are_all_there(self, paths):
+                # check that files are there
+                for p in paths:
+                        if p.startswith(os.path.sep):
+                                p = p[1:]
+                        file_path = os.path.join(self.get_img_path(), p)
+                        isthere = os.path.exists(file_path)
+                        if p.endswith(os.path.sep):
+                                if not os.path.isdir(file_path):
+                                        if not isthere:
+                                                print >> sys.stderr, "missing dir %s" % file_path
+                                        else:
+                                                print >> sys.stderr, "not dir: %s" % file_path
+                                        return False
+                        else:
+                                if not os.path.isfile(file_path):
+                                        if not isthere:
+                                                print >> sys.stderr, "missing file %s" % file_path
+                                        else:
+                                                print >> sys.stderr, "not file: %s" % file_path
+                                        return False
+                return True
+
+        def files_are_all_missing(self, paths):
+                # make sure all files are gone
+                for p in paths:
+                        file_path = os.path.join(self.get_img_path(), p)
+                        if os.path.isfile(file_path):
+                                print file_path
+                                return False
+                return True
+
         def remove_file(self, path):
                 os.unlink(os.path.join(self.get_img_path(), path))
 
+        def remove_dir(self, path):
+                os.rmdir(os.path.join(self.get_img_path(), path))
+
         def setUp(self):
                 pkg5unittest.SingleDepotTestCase.setUp(self)
                 self.make_misc_files(self.misc_files)
+                self.make_misc_files(self.additional_files)
+                self.plist = self.pkgsend_bulk(self.rurl, self.pkgs)
 
         def test_revert(self):
-                plist = self.pkgsend_bulk(self.rurl, self.pkgs)
                 self.image_create(self.rurl)
                 # try reverting non-editable files
                 self.pkg("install [email protected] [email protected] [email protected] [email protected]")
@@ -132,10 +215,10 @@
                 # revert damage to B, C, D by tag and test the parsable output.
                 self.pkg("revert -n --parsable=0 --tagged bob")
                 self.assertEqualParsable(self.output,
-                    affect_packages=[plist[1], plist[2], plist[3]])
+                    affect_packages=[self.plist[1], self.plist[2], self.plist[3]])
                 self.pkg("revert --parsable=0 --tagged bob")
                 self.assertEqualParsable(self.output,
-                    affect_packages=[plist[1], plist[2], plist[3]])
+                    affect_packages=[self.plist[1], self.plist[2], self.plist[3]])
                 self.pkg("verify A", exit=1)
                 self.pkg("verify B")
                 self.pkg("verify C")
@@ -159,12 +242,104 @@
                 self.pkg("verify A", exit=1)
                 self.pkg("revert /etc/file1")
                 self.pkg("revert /etc/file1", exit=4)
-
+                self.pkg("verify")
+                # check that we handle missing files when tagged
+                self.remove_file("etc/file2")
+                self.pkg("verify", exit=1)
+                self.pkg("revert --tagged bob")
+                self.pkg("verify")
+                # make sure we got the default contents
+                self.pkg("revert --tagged bob", exit=4)
                 # check that we handle files that don't exist correctly
                 self.pkg("revert /no/such/file", exit=1)
                 # since tags can be missing, just nothing to do for
                 # tags that we cannot find
                 self.pkg("revert --tagged no-such-tag", exit=4)
 
+        def test_revert_2(self):
+                """exercise new directory revert facility"""
+                self.image_create(self.rurl)
+                some_files = ["etc/A", "etc/B", "etc/C"]
+
+                # first try reverting tag that doesn't exist
+                self.pkg("install [email protected] W@1")
+                self.pkg("verify")
+                self.pkg("revert --tagged alice", 4)
+                self.pkg("verify")
+
+                # now revert a tag that exists, but doesn't need
+                # any work done
+                self.pkg("revert --tagged bob", 4)
+
+                # now create some unpackaged files
+                self.create_some_files(some_files)
+                self.assert_(self.files_are_all_there(some_files))
+                # revert them
+                self.pkg("revert --tagged bob", 0)
+                self.pkg("verify")
+                self.assert_(self.files_are_all_missing(some_files))
+
+                # now create some unpackaged directories and files
+                some_dirs = ["etc/X/", "etc/Y/", "etc/Z/C", "etc/X/XX/"]
+                self.create_some_files(some_dirs + some_files)
+                self.assert_(self.files_are_all_there(some_dirs + some_files))
+                # revert them
+                self.pkg("revert --tagged bob", 0)
+                self.pkg("verify")
+                self.assert_(self.files_are_all_missing(some_dirs + some_files))
+
+                # install a package w/ implicit directories
+                self.pkg("install [email protected]")
+                self.create_some_files(some_dirs + some_files + ["etc/wombat/XXX"])
+                self.assert_(self.files_are_all_there(some_dirs + some_files + ["etc/wombat/XXX"]))
+                # revert them
+                self.pkg("revert --tagged bob", 0)
+                self.pkg("verify")
+                self.assert_(self.files_are_all_missing(some_dirs + some_files))
+                self.assert_(self.files_are_all_there(["etc/wombat/XXX"]))
+                # mix and match w/ regular tests
+                self.pkg("install [email protected] [email protected] [email protected]")
+                self.pkg("verify")
+                self.damage_all_files()
+                self.create_some_files(some_dirs + some_files + ["etc/wombat/XXX"])
+                self.assert_(self.files_are_all_there(some_dirs + some_files + ["etc/wombat/XXX"]))
+                self.pkg("verify A", exit=1)
+                self.pkg("verify B", exit=1)
+                self.pkg("verify C", exit=1)
+                self.pkg("verify D", exit=1)
+                self.pkg("revert --tagged bob")
+                self.pkg("revert /etc/file1")
+                self.pkg("verify")
+                self.assert_(self.files_are_all_missing(some_dirs + some_files))
+                self.assert_(self.files_are_all_there(["etc/wombat/XXX"]))
+                # generate some problems
+                self.pkg("install Y")
+                self.pkg("verify")
+                self.remove_dir("etc/y-dir")
+                self.pkg("revert --tagged bob", 4)
+                self.pkg("fix Y")
+                self.pkg("verify")
+                self.pkg("revert --tagged bob", 4)
+
+        def test_revert_3(self):
+                """duplicate usage in /dev as per Ethan's mail"""
+                self.image_create(self.rurl)
+                some_files = ["dev/xxx", "dev/yyy", "dev/zzz",
+                              "dev/dir1/aaaa", "dev/dir1/bbbb", "dev/dir2/cccc",
+                              "dev/cfg/ffff", "dev/cfg/gggg",
+                              "dev/cfg/dir3/iiii", "dev/cfg/dir3/jjjj"]
+
+                some_dirs = ["dev/dir1/", "dev/dir1/", "dev/dir2/", "dev/cfg/dir3/"]
+                self.pkg("install dev dev2")
+                self.pkg("verify")
+                self.assert_(self.files_are_all_missing(some_dirs + some_files))
+                self.create_some_files(some_dirs + some_files)
+                self.assert_(self.files_are_all_there(some_dirs + some_files))
+                self.pkg("verify -v")
+		self.damage_files(["dev/cfg/bar2"])
+		self.pkg("revert -vvv --tagged init-dev")
+		self.pkg("verify -v")
+		self.assert_(self.files_are_all_missing(some_dirs + some_files))
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_search.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_search.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -137,6 +137,11 @@
             "basename   file      bin/example_path          pkg:/[email protected]\n"
         ])
 
+        res_remote_case_sensitive = set([
+            headers,
+            "pkg.fmri	set	test/example_pkg pkg:/[email protected]\n"
+        ])
+
         res_remote_bin = set([
             headers,
             "path       dir       bin                       pkg:/[email protected]\n"
@@ -382,6 +387,8 @@
                 self.pkg("search -a -r example_pkg")
 
                 self._search_op(True, "example_path", self.res_remote_path)
+                self._search_op(True, "':set:pkg.fmri:exAMple_pkg'",
+                    self.res_remote_case_sensitive, case_sensitive=False)
                 self._search_op(True, "'(example_path)'", self.res_remote_path)
                 self._search_op(True, "'<exam*:::>'",
                     self.res_remote_pkg_ret_pkg)
@@ -457,6 +464,9 @@
                 self.pkg("search -a -r 'e* AND <e*>'", exit=1)
                 self.pkg("search -a -r '<e*> OR e*'", exit=1)
                 self.pkg("search -a -r 'e* OR <e*>'", exit=1)
+                self._search_op(True, "pkg:/example_path", self.res_remote_path)
+                self.pkg("search -a -r -I ':set:pkg.fmri:exAMple_pkg'", exit=1)
+                self.assert_(self.errout == "" )
 
         def _run_local_tests(self):
                 outfile = os.path.join(self.test_root, "res")
@@ -530,6 +540,7 @@
                 self.pkg("search -a -l 'e* AND <e*>'", exit=1)
                 self.pkg("search -a -l '<e*> OR e*'", exit=1)
                 self.pkg("search -a -l 'e* OR <e*>'", exit=1)
+                self._search_op(False, "pkg:/example_path", self.res_local_path)
 
         def _run_local_empty_tests(self):
                 self.pkg("search -a -l example_pkg", exit=1)
@@ -951,6 +962,127 @@
                 # Test rebuilding the index with a missing manifest.
                 self.pkg("rebuild-index")
 
+        def test_15807844(self):
+                """ Check that pkg search for temporary sources is successful
+                when there no publishers configured in the image."""
+
+                rurl = self.dc.get_repo_url()
+                self.pkgsend_bulk(rurl, self.example_pkg10)
+                self.image_create()
+                expected = \
+                "INDEX ACTION VALUE PACKAGE\n" \
+                "basename file bin/example_path pkg:/[email protected]\n"
+                self.pkg("search -s %s example_path" % self.rurl)
+                actual = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected)
+                self.assertEqualDiff(expected, actual)
+                self.pkg("search example_path", exit=1)
+
+class TestSearchMultiPublisher(pkg5unittest.ManyDepotTestCase):
+
+        same_pub1 = """
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/bin
+            add file tmp/samepub_file1 mode=0555 owner=root group=bin path=/bin/samepub_file1
+            close """
+
+        same_pub2 = """
+            open [email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/bin
+            add file tmp/samepub_file2 mode=0555 owner=root group=bin path=/bin/samepub_file2
+            close """
+
+        example_pkg11 = """
+            open pkg://test1/[email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/bin
+            add file tmp/example_file mode=0555 owner=root group=bin path=/bin/example_path12
+            close """
+        
+        incorp_pkg11 = """
+            open pkg://test1/[email protected],5.11-0
+            add depend fmri=pkg://test1/[email protected],5.11-0 type=incorporate
+            close """
+
+        example_pkg12 = """
+            open pkg://test2/[email protected],5.11-0
+            add dir mode=0755 owner=root group=bin path=/bin
+            add file tmp/example_file mode=0555 owner=root group=bin path=/bin/example_path12
+            close """
+        
+        incorp_pkg12 = """
+            open pkg://test2/[email protected],5.11-0
+            add depend fmri=pkg://test2/[email protected],5.11-0 type=incorporate
+            close """
+
+        misc_files = {
+            "tmp/samepub_file1": "magic",
+            "tmp/samepub_file2": "magic",
+            "tmp/example_file": "magic",
+        }
+
+        def setUp(self):
+                pkg5unittest.ManyDepotTestCase.setUp(self,["samepub", "samepub"],
+                    start_depots=True)
+                self.make_misc_files(self.misc_files)
+                self.durl1 = self.dcs[1].get_depot_url()
+                self.durl2 = self.dcs[2].get_depot_url()
+
+        def test_7140657(self):
+                """ Check that pkg search with -s works as intended when there are
+                two repositories with same publisher name configured."""
+
+                self.pkgsend_bulk(self.durl1, self.same_pub1, refresh_index=True)
+                self.pkgsend_bulk(self.durl2, self.same_pub2, refresh_index=True)
+                self.image_create(self.durl1, prefix="samepub")
+                self.pkg("set-publisher -g %s samepub" % self.durl2)
+                self.pkg("search -s %s samepub_file1" % self.durl1)
+
+                result_same_pub = \
+                "INDEX ACTION VALUE PACKAGE\n" \
+                "basename file bin/samepub_file1 pkg:/[email protected]\n"
+
+                actual = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(result_same_pub)
+                self.assertEqualDiff(expected, actual)
+                self.pkg("search -s %s samepub_file1" % self.durl2, exit=1)
+
+        def test_16190165(self):
+                """ Check that pkg search works fine with structured queries
+                    and the scheme name "pkg://" in the query """
+		
+                self.pkgsend_bulk(self.durl1, self.example_pkg11, refresh_index=True)
+                self.pkgsend_bulk(self.durl2, self.example_pkg12, refresh_index=True)
+                self.pkgsend_bulk(self.durl1, self.incorp_pkg11, refresh_index=True)
+                self.pkgsend_bulk(self.durl2, self.incorp_pkg12, refresh_index=True)
+                self.image_create(self.durl1, prefix="test1")
+                self.pkg("set-publisher -g %s test2" % self.durl2)
+
+                expected_out1 = \
+                "incorporate\tdepend\tpkg://test1/[email protected],5.11-0\tpkg:/[email protected]\n" \
+                "incorporate\tdepend\tpkg://test2/[email protected],5.11-0\tpkg:/[email protected]\n"
+
+                self.pkg("search -H :depend:incorporate:example_pkg",
+                     exit=0)
+                actual = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected_out1)
+                self.assertEqualDiff(expected, actual)
+
+        	expected_out2 = \
+		"pkg.fmri\tset\ttest1/example_pkg\tpkg:/[email protected]\n" \
+                "incorporate\tdepend\tpkg://test1/[email protected],5.11-0\tpkg:/[email protected]\n" \
+                "pkg.fmri\tset\ttest2/example_pkg\tpkg:/[email protected]\n" \
+                "incorporate\tdepend\tpkg://test2/[email protected],5.11-0\tpkg:/[email protected]\n"
+
+		self.pkg("search -H pkg://test1/example_pkg",exit=0)
+                actual = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected_out2)
+                self.assertEqualDiff(expected, actual)
+
+		self.pkg("search -H pkg:/example_pkg",exit=0)
+                actual = self.reduceSpaces(self.output)
+                expected = self.reduceSpaces(expected_out2)
+                self.assertEqualDiff(expected, actual)
+
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkg_sysrepo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_sysrepo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -64,7 +64,7 @@
                 self.required_names = req_names
                 self.origins = origins
 
-class TestSysrepo(pkg5unittest.ManyDepotTestCase):
+class TestSysrepo(pkg5unittest.ApacheDepotTestCase):
         """Tests pkg interaction with the system repository."""
 
         # Tests in this suite use the read only data directory.
@@ -102,36 +102,8 @@
 test4\ttrue\ttrue\ttrue\t\t\t\t
 """
 
-        def killalldepots(self):
-                try:
-                        pkg5unittest.ManyDepotTestCase.killalldepots(self)
-                finally:
-                        if self.sc:
-                                self.debug("stopping sysrepo")
-                                try:
-                                        self.sc.stop()
-                                except Exception, e:
-                                        try:
-                                                self.debug("killing sysrepo")
-                                                self.sc.kill()
-                                        except Exception, e:
-                                                pass
-                        for ac in self.acs.values():
-                                self.debug("stopping https apache proxy")
-                                try:
-                                        ac.stop()
-                                except Exception,e :
-                                        try:
-                                                self.debug(
-                                                    "killing apache instance")
-                                                self.ac.kill()
-                                        except Exception, e:
-                                                pass
-
         def setUp(self):
                 # These need to be set before calling setUp in case setUp fails.
-                self.sc = None
-                self.acs = {}
                 self.smf_cmds = {}
 
                 # These need to set to allow the smf commands to give the right
@@ -186,7 +158,7 @@
                 # the property to the value.  The list of PC objects represent
                 # the configuration of each publisher.
                 #
-                # The self.configs dictionary is used to create images who
+                # The self.configs dictionary is used to create images whose
                 # configuration is used by pkg.sysrepo to create the
                 # configuration files needed to set up a system-repository
                 # instance for that image.
@@ -357,8 +329,8 @@
                         fh.write(self.https_conf % cd)
 
                 ac = pkg5unittest.ApacheController(conf_path, https_port,
-                    instance_dir, https=True)
-                self.acs[pc.url] = ac
+                    instance_dir, testcase=self, https=True)
+                self.register_apache_controller(pc.url, ac)
                 ac.start()
                 return ac
 
@@ -471,6 +443,9 @@
                         self.image_destroy()
 
         def __set_responses(self, name, update_conf=True):
+                """Sets the system-repository to use a named configuration
+                when providing responses."""
+
                 if name not in self.__configured_names:
                         raise RuntimeError("%s hasn't been prepared for this "
                             "test." % name)
@@ -497,8 +472,13 @@
                 if uid != new_gid or gid != new_gid:
                         misc.recursive_chown_dir(self.common_config_dir, uid,
                             gid)
-                if update_conf and self.sc:
-                        self.sc.conf = self.apache_confs[name]
+                if update_conf and "sysrepo" in self.acs:
+                        # changing configuration without registering a new
+                        # ApacheController is safe even if the new configuration
+                        # specifies a different port, because the controller
+                        # gets stopped/started by the __set_conf(..)
+                        # method of ApacheController if the process is running.
+                        self.acs["sysrepo"].conf = self.apache_confs[name]
 
         def __check_publisher_info(self, expected, set_debug_value=True,
             su_wrap=False, env_arg=None):
@@ -543,10 +523,11 @@
                 self.__prep_configuration("all-access",
                     use_config_cache=use_config_cache)
                 self.__set_responses("all-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["all-access"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 # Make sure that the publisher catalogs were created.
                 for n in ("test1", "test12", "test3"):
@@ -627,16 +608,17 @@
                 self.__prep_configuration(["all-access", "none", "test12-test3",
                     "test3"])
                 self.__set_responses("all-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["none"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
+                self.register_apache_controller("sysrepo", sc)
 
-                self.sc.start()
+                sc.start()
                 self.assertRaises(apx.CatalogRefreshException,
                     self.image_create, props={"use-system-repo": True})
-                self.sc.conf = self.apache_confs["all-access"]
+                sc.conf = self.apache_confs["all-access"]
                 api_obj = self.image_create(props={"use-system-repo": True})
-                self.sc.conf = self.apache_confs["none"]
+                sc.conf = self.apache_confs["none"]
 
                 expected =  self.expected_all_access % \
                     {"durl1": self.durl1, "durl2": self.durl2,
@@ -657,7 +639,7 @@
                 self.assertRaises(tx.TransportFailures, self._api_install,
                     api_obj, ["bar"], refresh_catalogs=False)
 
-                self.sc.conf = self.apache_confs["test3"]
+                sc.conf = self.apache_confs["test3"]
                 self.pkg("list -a")
                 self.pkg("contents -rm example_pkg", exit=1)
                 self.pkg("contents -rm foo", exit=1)
@@ -669,7 +651,7 @@
                 self._api_install(api_obj, ["bar"], refresh_catalogs=False)
 
 
-                self.sc.conf = self.apache_confs["test12-test3"]
+                sc.conf = self.apache_confs["test12-test3"]
                 self.pkg("list -a")
                 self.pkg("contents -rm example_pkg", exit=1)
                 self.pkg("contents -rm foo")
@@ -677,7 +659,7 @@
                     api_obj, ["example_pkg"], refresh_catalogs=False)
                 self._api_install(api_obj, ["foo"], refresh_catalogs=False)
 
-                self.sc.conf = self.apache_confs["all-access"]
+                sc.conf = self.apache_confs["all-access"]
                 self.pkg("list -a")
                 self.pkg("contents -rm example_pkg")
                 self._api_install(api_obj, ["example_pkg"])
@@ -721,10 +703,11 @@
                 self.__prep_configuration(["test1", "none",
                     "mirror-access-user"])
                 self.__set_responses("test1")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["test1"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 # Test that most modifications to a system publisher fail.
@@ -770,7 +753,7 @@
                 # Change the proxy configuration so that the image can't use it
                 # to communicate with the depot. This forces communication to
                 # go through the user configured origin.
-                self.sc.conf = self.apache_confs["none"]
+                sc.conf = self.apache_confs["none"]
 
                 # Check that the catalog can't be refreshed and that the
                 # communcation with the repository fails.
@@ -801,7 +784,7 @@
 
                 # Reenable access to the depot to make sure nothing has been
                 # broken in the image.
-                self.sc.conf = self.apache_confs["test1"]
+                sc.conf = self.apache_confs["test1"]
                 self.pkg("refresh --full")
 
                 # Find the hashes that will be included in the urls of the
@@ -813,7 +796,7 @@
 
                 # Check that a user can add and remove mirrors,
                 # but can't remove repo-provided mirrors
-                self.sc.conf = self.apache_confs["mirror-access-user"]
+                sc.conf = self.apache_confs["mirror-access-user"]
                 self.__set_responses("mirror-access-user")
                 self.pkg("set-publisher -m %s test12" % self.rurl2)
                 expected_mirrors = """\
@@ -860,7 +843,6 @@
 
                 self.__check_publisher_info(expected)
 
-
         def test_04_changing_syspub_configuration(self):
                 """Test that changes to the syspub/0 response are handled
                 correctly by the client."""
@@ -870,10 +852,11 @@
                 self.__prep_configuration(["none", "test1-test12",
                     "test1-test3", "test12"])
                 self.__set_responses("none")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["none"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 expected = """\
@@ -1032,10 +1015,11 @@
                 # Create an image with no user configured publishers and no
                 # system configured publishers.
                 self.__set_responses("none")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["none"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 expected = """\
 PUBLISHER\tSTICKY\tSYSPUB\tENABLED\tTYPE\tSTATUS\tURI\tPROXY
@@ -1045,13 +1029,8 @@
                 # Have the user configure test1 at the same time that test1 is
                 # made a system publisher.
                 self.__set_responses("test1")
-                # This fails in the same way that doing set-publisher -p for a
-                # repository which provides packages for an already configured
-                # publisher fails.
-                self.pkg("set-publisher -p %s" % self.rurl1, exit=1)
-                # Adding the origin to the publisher which now exists should
-                # work fine.
-                self.pkg("set-publisher -g %s test1" % self.rurl1)
+
+                self.pkg("set-publisher -p %s" % self.rurl1)
                 expected = """\
 PUBLISHER\tSTICKY\tSYSPUB\tENABLED\tTYPE\tSTATUS\tURI\tPROXY
 test1\ttrue\ttrue\ttrue\torigin\tonline\t%(rurl1)s/\t-
@@ -1059,6 +1038,10 @@
 """ % {"rurl1": self.rurl1, "durl1": self.durl1, "port": self.sysrepo_port}
                 self.__check_publisher_info(expected)
 
+                # Adding the origin to the publisher which now exists should
+                # fail.
+                self.pkg("set-publisher -g %s test1" % self.rurl1, exit=1)
+
                 # The user adds an origin to test12 at the same time that test12
                 # first becomes known to the image.
                 self.__set_responses("test12")
@@ -1112,10 +1095,11 @@
 
                 self.__prep_configuration(["all-access", "none", "test1"])
                 self.__set_responses("none")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["none"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 self.pkg("set-publisher -p %s" % self.rurl3)
@@ -1262,11 +1246,12 @@
                 self.__prep_configuration(["all-access"],
                     port=self.sysrepo_alt_port)
                 self.__set_responses("all-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["all-access"],
                     self.sysrepo_alt_port, self.common_config_dir,
                     testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 old_psu = os.environ.get("PKG_SYSREPO_URL", None)
                 os.environ["PKG_SYSREPO_URL"] = "localhost:%s" % \
                     self.sysrepo_alt_port
@@ -1287,10 +1272,11 @@
                         self.dcs[i].kill(now=True)
                 self.__prep_configuration(["all-access-f", "none"])
                 self.__set_responses("all-access-f")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["all-access-f"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 # Find the hashes that will be included in the urls of the
@@ -1344,10 +1330,11 @@
                 self.__prep_configuration(["all-access", "all-access-f",
                     "none"])
                 self.__set_responses("all-access-f")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["all-access-f"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 # Find the hashes that will be included in the urls of the
@@ -1383,10 +1370,11 @@
                 self.__prep_configuration(["all-access", "all-access-f",
                     "mirror-access", "mirror-access-f", "none"])
                 self.__set_responses("mirror-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["mirror-access"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 # Find the hashes that will be included in the urls of the
@@ -1485,10 +1473,11 @@
                 self.__prep_configuration(["https-access", "none"],
                     use_config_cache=use_config_cache)
                 self.__set_responses("https-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["https-access"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 expected = """\
@@ -1532,10 +1521,11 @@
                 self.__prep_configuration(["disabled"],
                     use_config_cache=use_config_cache)
                 self.__set_responses("disabled")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["disabled"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 expected = """\
 PUBLISHER\tSTICKY\tSYSPUB\tENABLED\tTYPE\tSTATUS\tURI\tPROXY
@@ -1561,10 +1551,11 @@
                 self.__prep_configuration(["nourl"],
                     use_config_cache=use_config_cache)
                 self.__set_responses("nourl")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["nourl"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 expected_empty = """\
 PUBLISHER\tSTICKY\tSYSPUB\tENABLED\tTYPE\tSTATUS\tURI\tPROXY
@@ -1616,10 +1607,11 @@
 
                 self.__prep_configuration(["all-access", "none"])
                 self.__set_responses("all-access")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["all-access"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 expected =  self.expected_all_access % \
@@ -1643,7 +1635,7 @@
 
                 # Test that when the sysrepo isn't available, unprivileged users
                 # don't lose functionality.
-                self.sc.stop()
+                sc.stop()
                 # Since the last privileged command was done when no
                 # system-publishers were available, that's what's expected when
                 # the system repository isn't available.
@@ -1656,12 +1648,12 @@
 
                 # Now do a privileged command command to change what the state
                 # on disk is.
-                self.sc.start()
+                sc.start()
                 expected =  self.expected_all_access % \
                     {"durl1": self.durl1, "durl2": self.durl2,
                     "durl3": self.durl3, "port": self.sysrepo_port}
                 self.__check_publisher_info(expected)
-                self.sc.stop()
+                sc.stop()
 
                 self.__check_publisher_info(expected, su_wrap=True)
                 self.pkg("property", su_wrap=True)
@@ -1674,10 +1666,11 @@
                 conf_name = "img-sig-ignore"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 self.pkg("property -H signature-policy", su_wrap=True)
@@ -1694,10 +1687,11 @@
                 conf_name = "img-sig-require"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 self.pkg("property -H signature-policy")
@@ -1715,10 +1709,11 @@
                 conf_name = "img-sig-req-names"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
 
                 api_obj = self.image_create(props={"use-system-repo": True})
 
@@ -1742,10 +1737,11 @@
                 conf_name = "pub-sig-ignore"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 self.pkg("publisher test1", su_wrap=True)
@@ -1763,10 +1759,11 @@
                 conf_name = "pub-sig-require"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 pubs = api_obj.get_publishers()
@@ -1783,11 +1780,11 @@
                 conf_name = "pub-sig-reqnames"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
-
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 pubs = api_obj.get_publishers()
@@ -1807,10 +1804,11 @@
                 conf_name = "pub-sig-mixed"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
 
                 pubs = api_obj.get_publishers()
@@ -1836,10 +1834,11 @@
                 conf_name = "img-pub-sig-mixed"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
 
                 api_obj = self.image_create(props={"use-system-repo": True})
 
@@ -1877,10 +1876,11 @@
                 conf_name = "test1-test3"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 self.pkgsend_bulk(self.rurl1, self.foo11)
                 self.pkgsend_bulk(self.rurl3, self.bar11)
@@ -1894,10 +1894,11 @@
                 conf_name = "test1-test3-f"
                 self.__prep_configuration([conf_name])
                 self.__set_responses(conf_name)
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs[conf_name], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
                 api_obj = self.image_create(props={"use-system-repo": True})
                 self.pkgsend_bulk(self.rurl1, self.foo11)
                 self.pkgsend_bulk(self.rurl3, self.bar11)
@@ -1928,6 +1929,7 @@
                 sc = pkg5unittest.SysrepoController(
                     self.apache_confs["test1-test12-test12"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
+                self.register_apache_controller("sysrepo", sc)
                 sc.start()
 
                 # enable the test1 and test12 publishers
@@ -1953,10 +1955,11 @@
                 self.__prep_configuration(["test1", "test1-test12",
                     "test1-test12-test12"])
                 self.__set_responses("test1-test12")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["test1-test12"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
 
                 api_obj = self.image_create(props={"use-system-repo": True})
 
@@ -2084,10 +2087,11 @@
 
                 self.__prep_configuration(["test1"])
                 self.__set_responses("test1")
-                self.sc = pkg5unittest.SysrepoController(
+                sc = pkg5unittest.SysrepoController(
                     self.apache_confs["test1"], self.sysrepo_port,
                     self.common_config_dir, testcase=self)
-                self.sc.start()
+                self.register_apache_controller("sysrepo", sc)
+                sc.start()
 
                 api_obj = self.image_create(props={"use-system-repo": True})
 
--- a/src/tests/cli/t_pkg_temp_sources.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_temp_sources.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -422,6 +422,10 @@
                 """Verify that the info operation works as expected for
                 temporary origins.
                 """
+		# because we compare date strings we must run this in
+		# a consistent locale, which we made 'C'
+
+		os.environ['LC_ALL'] = 'C'
 
                 # Create an image and verify no packages are known.
                 self.image_create(self.empty_rurl, prefix=None)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_pkg_varcet.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,632 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+import pkg5unittest
+
+import os
+import pkg.fmri as fmri
+import pkg.portable as portable
+import pkg.misc as misc
+import pkg.p5p
+import shutil
+import stat
+import tempfile
+import unittest
+
+from pkg.client.pkgdefs import EXIT_OOPS
+
+class TestPkgVarcet(pkg5unittest.SingleDepotTestCase):
+
+        # Don't discard repository or setUp() every test.
+        persistent_setup = True
+
+        pkg_foo = """
+            open [email protected]
+            add file tmp/non-debug path=usr/bin/foo mode=0755 owner=root group=root
+            add file tmp/man path=usr/man/man1/foo.1 mode=0444 owner=root group=root
+            close
+            open [email protected]
+            add set name=variant.icecream value=neapolitan value=strawberry
+            add file tmp/debug path=usr/bin/foo mode=0755 owner=root group=root variant.debug.foo=true
+            add file tmp/non-debug path=usr/bin/foo mode=0755 owner=root group=root variant.debug.foo=false
+            add file tmp/neapolitan path=etc/icecream mode=0644 owner=root group=root variant.icecream=neapolitan
+            add file tmp/strawberry path=etc/icecream mode=0644 owner=root group=root variant.icecream=strawberry
+            add file tmp/man path=usr/man/man1/foo.1 mode=0444 owner=root group=root facet.doc.man=true
+            add file tmp/doc path=usr/share/foo/README mode=0444 owner=root group=root facet.doc.txt=true
+            add file tmp/pdf path=usr/share/foo/README.pdf mode=0444 owner=root group=root facet.doc.pdf=true
+            open [email protected]
+            add set name=pkg.facet value=doc.man value=doc.txt value=doc.pdf
+            add set name=pkg.variant value=icecream value=debug.foo
+            add set name=variant.icecream value=neapolitan value=strawberry
+            add file tmp/debug path=usr/bin/foo mode=0755 owner=root group=root variant.debug.foo=true
+            add file tmp/non-debug path=usr/bin/foo mode=0755 owner=root group=root variant.debug.foo=false
+            add file tmp/neapolitan path=etc/icecream mode=0644 owner=root group=root variant.icecream=neapolitan
+            add file tmp/strawberry path=etc/icecream mode=0644 owner=root group=root variant.icecream=strawberry
+            add file tmp/man path=usr/man/man1/foo.1 mode=0444 owner=root group=root facet.doc.man=true
+            add file tmp/doc path=usr/share/foo/README mode=0444 owner=root group=root facet.doc.txt=true
+            add file tmp/pdf path=usr/share/foo/README.pdf mode=0444 owner=root group=root facet.doc.pdf=true
+            close """
+
+        pkg_unknown = """
+            open [email protected]
+            add set name=variant.unknown value=bar value=foo
+            add file tmp/non-debug path=usr/bin/bar mode=0755 owner=root group=root variant.unknown=bar
+            add file tmp/non-debug path=usr/bin/foo mode=0755 owner=root group=root variant.unknown=foo
+            close """
+
+        pkg_need_foo = """
+            open [email protected]
+            add depend type=require fmri=foo
+            """
+
+        misc_files = ["tmp/debug", "tmp/non-debug", "tmp/neapolitan",
+            "tmp/strawberry", "tmp/doc", "tmp/man", "tmp/pdf"]
+
+        def setUp(self):
+                pkg5unittest.SingleDepotTestCase.setUp(self)
+                self.make_misc_files(self.misc_files)
+                self.pkgsend_bulk(self.rurl, [
+                    getattr(self, p)
+                    for p in dir(self)
+                    if p.startswith("pkg_") and isinstance(getattr(self, p),
+                        basestring)
+                ])
+
+        def __assert_varcet_matches_default(self, cmd, expected, errout=None,
+            exit=0, opts=misc.EmptyI, names=misc.EmptyI, su_wrap=False):
+                if errout is None and exit != 0:
+                        # Assume there should be error output for non-zero exit
+                        # if not explicitly indicated.
+                        errout = True
+
+                self.pkg("%s %s -H %s" % (cmd, " ".join(opts), " ".join(names)),
+                    exit=exit, su_wrap=su_wrap)
+                self.assertEqualDiff(expected, self.reduceSpaces(self.output))
+                if errout:
+                        self.assert_(self.errout != "")
+                else:
+                        self.assertEqualDiff("", self.errout)
+
+        def __assert_varcet_matches_tsv(self, cmd, expected, errout=None,
+            exit=0, opts=misc.EmptyI, names=misc.EmptyI, su_wrap=False):
+                self.pkg("%s %s -H -F tsv %s" % (cmd, " ".join(opts),
+                    " ".join(names)), exit=exit, su_wrap=su_wrap)
+                self.assertEqualDiff(expected, self.output)
+                if errout:
+                        self.assert_(self.errout != "")
+                else:
+                        self.assertEqualDiff("", self.errout)
+
+        def __assert_varcet_fails(self, cmd, operands, errout=True, exit=1,
+            su_wrap=False):
+                self.pkg("%s %s" % (cmd, operands), exit=exit, su_wrap=su_wrap) 
+                if errout:
+                        self.assert_(self.errout != "")
+                else:
+                        self.assertEqualDiff("", self.errout)
+
+        def __assert_facet_matches_default(self, *args, **kwargs):
+                self.__assert_varcet_matches_default("facet", *args,
+                    **kwargs)
+
+        def __assert_facet_matches_tsv(self, *args, **kwargs):
+                self.__assert_varcet_matches_tsv("facet", *args,
+                    **kwargs)
+
+        def __assert_facet_matches(self, exp_def, **kwargs):
+                exp_tsv = exp_def.replace(" ", "\t")
+                self.__assert_varcet_matches_default("facet", exp_def,
+                    **kwargs)
+                self.__assert_varcet_matches_tsv("facet", exp_tsv,
+                    **kwargs)
+
+        def __assert_facet_fails(self, *args, **kwargs):
+                self.__assert_varcet_fails("facet", *args, **kwargs)
+
+        def __assert_variant_matches_default(self, *args, **kwargs):
+                self.__assert_varcet_matches_default("variant", *args,
+                    **kwargs)
+
+        def __assert_variant_matches_tsv(self, *args, **kwargs):
+                self.__assert_varcet_matches_tsv("variant", *args,
+                    **kwargs)
+
+        def __assert_variant_matches(self, exp_def, **kwargs):
+                exp_tsv = exp_def.replace(" ", "\t")
+                self.__assert_varcet_matches_default("variant", exp_def,
+                    **kwargs)
+                self.__assert_varcet_matches_tsv("variant", exp_tsv,
+                    **kwargs)
+
+        def __assert_variant_fails(self, *args, **kwargs):
+                self.__assert_varcet_fails("variant", *args, **kwargs)
+
+        def __test_foo_facet_upgrade(self, pkg):
+                #
+                # Next, verify output after upgrading package to faceted
+                # version.
+                #
+                self.pkg("update %s" % pkg)
+
+                # Verify output for no options and no patterns.
+                exp_def = """\
+facet.doc.* False local
+facet.doc.html False local
+facet.doc.man False local
+facet.doc.txt True local
+"""
+                self.__assert_facet_matches(exp_def)
+
+                # Unmatched because facet is not explicitly set.
+                self.__assert_facet_fails("doc.pdf")
+                self.__assert_facet_fails("'*pdf'")
+
+                # Matched case for explicitly set.
+                exp_def = """\
+facet.doc.* False local
+facet.doc.txt True local
+"""
+                names = ("'facet.doc.[*]'", "doc.txt")
+                self.__assert_facet_matches(exp_def, names=names)
+
+                # Verify -a output.
+                exp_def = """\
+facet.doc.* False local
+facet.doc.html False local
+facet.doc.man False local
+facet.doc.pdf False local
+facet.doc.txt True local
+"""
+                opts = ("-a",)
+                self.__assert_facet_matches(exp_def, opts=opts)
+
+                # Matched case for explicitly set and those in packages.
+                exp_def = """\
+facet.doc.* False local
+facet.doc.pdf False local
+facet.doc.txt True local
+"""
+                names = ("'facet.doc.[*]'", "*pdf", "facet.doc.txt")
+                opts = ("-a",)
+                self.__assert_facet_matches(exp_def, opts=opts, names=names)
+
+                # Verify -i output.
+                exp_def = """\
+facet.doc.man False local
+facet.doc.pdf False local
+facet.doc.txt True local
+"""
+                opts = ("-i",)
+                self.__assert_facet_matches(exp_def, opts=opts)
+
+                # Unmatched because facet is not used in package.
+                self.__assert_facet_fails("-i doc.html")
+                self.__assert_facet_fails("-i '*html'")
+
+                # Matched case in packages.
+                exp_def = """\
+facet.doc.man False local
+facet.doc.pdf False local
+"""
+                names = ("'facet.*[!t]'",)
+                opts = ("-i",)
+                self.__assert_facet_matches(exp_def, opts=opts, names=names)
+
+                exp_def = """\
+facet.doc.pdf False local
+"""
+                names = ("'*pdf'",)
+                opts = ("-i",)
+                self.__assert_facet_matches(exp_def, opts=opts, names=names)
+
+                # Now uninstall package and verify output (to ensure any
+                # potentially cached information has been updated).
+                self.pkg("uninstall foo")
+
+                exp_def = """\
+facet.doc.* False local
+facet.doc.html False local
+facet.doc.man False local
+facet.doc.txt True local
+"""
+
+                # Output should be the same for both -a and default cases with
+                # no packages installed.
+                for opts in ((), ("-a",)):
+                        self.__assert_facet_matches(exp_def, opts=opts)
+
+                # No output expected for -i.
+                opts = ("-i",)
+                self.__assert_facet_matches("", opts=opts)
+
+        def test_00_facet(self):
+                """Verify facet subcommand works as expected."""
+
+                # create an image
+                variants = { "variant.icecream": "strawberry" }
+                self.image_create(self.rurl, variants=variants)
+
+                # Verify invalid options handled gracefully.
+                self.__assert_facet_fails("-z", exit=2)
+                self.__assert_facet_fails("-fi", exit=2)
+
+                #
+                # First, verify output before setting any facets or installing
+                # any packages.
+                #
+
+                # Output should be the same for all cases with no facets set and
+                # no packages installed.
+                for opts in ((), ("-i",), ("-a",)):
+                        # No operands specified case.
+                        self.__assert_facet_matches("", opts=opts)
+
+                        # Unprivileged user case.
+                        self.__assert_facet_matches("", opts=opts, su_wrap=True)
+
+                        # Unmatched case.
+                        self.__assert_facet_matches_default("", opts=opts,
+                            names=("bogus",), exit=1)
+
+                        # Unmatched case tsv; subtly different as no error
+                        # output is expected.
+                        self.__assert_facet_matches_tsv("", opts=opts,
+                            names=("bogus",), exit=1, errout=False)
+
+                #
+                # Next, verify output after setting facets.
+                #
+
+                # Set some facets.
+                self.pkg("change-facet 'doc.*=False' doc.man=False "
+                    "facet.doc.html=False facet.doc.txt=True")
+
+                exp_def = """\
+facet.doc.* False local
+facet.doc.html False local
+facet.doc.man False local
+facet.doc.txt True local
+"""
+
+                # Output should be the same for both -a and default cases with
+                # no packages installed.
+                for opts in ((), ("-a",)):
+                        self.__assert_facet_matches(exp_def, opts=opts)
+
+                #
+                # Next, verify output after installing unfaceted package.
+                #
+                self.pkg("install [email protected]")
+
+                # Verify output for no options and no patterns.
+                exp_def = """\
+facet.doc.* False local
+facet.doc.html False local
+facet.doc.man False local
+facet.doc.txt True local
+"""
+                self.__assert_facet_matches(exp_def)
+
+                # Verify -a output.
+                opts = ("-a",)
+                self.__assert_facet_matches(exp_def, opts=opts)
+
+                # Verify -i output.
+                opts = ("-i",)
+                self.__assert_facet_matches("", opts=opts)
+
+                # Test upgraded package that does not declare all
+                # facets/variants.
+                self.__test_foo_facet_upgrade("[email protected]")
+
+                # Reinstall and then retest with upgraded package that declares
+                # all facets/variants.
+                self.pkg("install [email protected]")
+                self.__test_foo_facet_upgrade("[email protected]")
+
+        def __test_foo_variant_upgrade(self, pkg, variants):
+                #
+                # Next, verify output after upgrading package to varianted
+                # version.
+                #
+                self.pkg("update %s" % pkg)
+
+                # Verify output for no options and no patterns.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+                self.__assert_variant_matches(exp_def)
+
+                # Unmatched because variant is not explicitly set.
+                self.__assert_variant_fails("debug.foo")
+                self.__assert_variant_fails("'*foo'")
+
+                # Matched case for explicitly set.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.opensolaris.zone global
+""" % variants
+                names = ("arch", "'variant.*zone'")
+                self.__assert_variant_matches(exp_def, names=names)
+
+                # Verify -a output.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.debug.foo false
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+                opts = ("-a",)
+                self.__assert_variant_matches(exp_def, opts=opts)
+
+                # Matched case for explicitly set and those in packages.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.debug.foo false
+variant.opensolaris.zone global
+""" % variants
+                names = ("'variant.debug.*'", "arch", "'*zone'")
+                opts = ("-a",)
+                self.__assert_variant_matches(exp_def, opts=opts, names=names)
+
+                # Verify -i output.
+                exp_def = """\
+variant.debug.foo false
+variant.icecream strawberry
+""" % variants
+                opts = ("-i",)
+                self.__assert_variant_matches(exp_def, opts=opts)
+
+                # Unmatched because variant is not used in package.
+                self.__assert_variant_fails("-i opensolaris.zone")
+                self.__assert_variant_fails("-i '*arch'")
+
+                # Verify -v and -av output.
+                exp_def = """\
+variant.debug.foo false
+variant.debug.foo true
+variant.icecream neapolitan
+variant.icecream strawberry
+"""
+                for opts in (("-v",), ("-av",)):
+                        self.__assert_variant_matches(exp_def, opts=opts)
+
+                exp_def = """\
+variant.icecream neapolitan
+variant.icecream strawberry
+""" % variants
+                names = ("'ice*'",)
+                opts = ("-av",)
+                self.__assert_variant_matches(exp_def, opts=opts, names=names)
+
+                # Matched case in packages.
+                exp_def = """\
+variant.icecream strawberry
+""" % variants
+                names = ("'variant.*[!o]'",)
+                opts = ("-i",)
+                self.__assert_variant_matches(exp_def, opts=opts, names=names)
+
+                exp_def = """\
+variant.debug.foo false
+""" % variants
+                names = ("*foo",)
+                opts = ("-i",)
+                self.__assert_variant_matches(exp_def, opts=opts, names=names)
+
+                # Now uninstall package and verify output (to ensure any
+                # potentially cached information has been updated).
+                self.pkg("uninstall foo")
+
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+
+                # Output should be the same for both -a and default cases with
+                # no packages installed.
+                for opts in ((), ("-a",)):
+                        self.__assert_variant_matches(exp_def, opts=opts)
+
+                # No output expected for -v, -av, -i, or -iv.
+                for opts in (("-v",), ("-av",), ("-i",), ("-iv",)):
+                        self.__assert_variant_matches("", opts=opts)
+
+        def test_01_variant(self):
+                """Verify variant subcommand works as expected."""
+
+                # create an image
+                self.image_create(self.rurl)
+
+                # Get variant data.
+                api_obj = self.get_img_api_obj()
+                variants = dict(v[:-1] for v in api_obj.gen_variants(
+                    api_obj.VARIANT_IMAGE))
+
+                # Verify invalid options handled gracefully.
+                self.__assert_variant_fails("-z", exit=2)
+                self.__assert_variant_fails("-ai", exit=2)
+                self.__assert_variant_fails("-aiv", exit=2)
+
+                #
+                # First, verify output before setting any variants or installing
+                # any packages.
+                #
+
+                # Output should be the same for -a and default cases with no
+                # variants set and no packages installed.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.opensolaris.zone global
+""" % variants
+
+                for opts in ((), ("-a",)):
+                        # No operands specified case.
+                        self.__assert_variant_matches(exp_def, opts=opts)
+
+                        # Unprivileged user case.
+                        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",)):
+                        self.__assert_variant_matches("", opts=opts)
+
+                #
+                # Next, verify output after setting variants.
+                #
+
+                # Set some variants.
+                self.pkg("change-variant variant.icecream=strawberry")
+
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+
+                # Output should be the same for both -a and default cases with
+                # no packages installed.
+                for opts in ((), ("-a",)):
+                        self.__assert_variant_matches(exp_def, opts=opts)
+
+                #
+                # Next, verify output after installing unvarianted package.
+                #
+                self.pkg("install [email protected]")
+
+                # Verify output for no options and no patterns.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+                self.__assert_variant_matches(exp_def)
+
+                # Verify -a output.
+                opts = ("-a",)
+                self.__assert_variant_matches(exp_def, opts=opts)
+
+                # Verify -v, -av, -i, and -iv output.
+                for opts in (("-v",), ("-av",), ("-i",), ("-iv",)):
+                        self.__assert_variant_matches("", opts=opts)
+
+                # Test upgraded package that does not declare all
+                # facets/variants.
+                self.__test_foo_variant_upgrade("[email protected]", variants)
+
+                # Reinstall and then retest with upgraded package that declares
+                # all facets/variants.
+                self.pkg("install [email protected]")
+                self.__test_foo_variant_upgrade("[email protected]", variants)
+
+                # Next, verify output after installing package with unknown
+                # variant.
+                self.pkg("install [email protected]")
+
+                # Verify output for no options and no patterns.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+""" % variants
+                self.__assert_variant_matches(exp_def)
+
+                # Verify -a output.
+                exp_def = """\
+variant.arch %(variant.arch)s
+variant.icecream strawberry
+variant.opensolaris.zone global
+variant.unknown 
+""" % variants
+                self.__assert_variant_matches(exp_def, opts=("-a",))
+
+                # Verify -i output.
+                exp_def = """\
+variant.unknown 
+""" % variants
+                self.__assert_variant_matches(exp_def, opts=("-i",))
+
+                # Verify -v, -av, and -iv output.
+                for opts in (("-v",), ("-av",), ("-iv",)):
+                        exp_def = """\
+variant.unknown bar
+variant.unknown foo
+""" % variants
+                        self.__assert_variant_matches(exp_def, opts=opts)
+
+        def test_02_varcet_reject(self):
+                """Verify that if we try to --reject packages that should get
+                removed we invoke the solver."""
+
+                # create an image
+                variants = { "variant.icecream": "strawberry" }
+                self.image_create(self.rurl, variants=variants)
+
+                # install a package with a dependency
+                self.pkg("install [email protected]")
+
+                # Set some facets/variant while rejecting a random package.
+                self.pkg("change-facet --reject=nothing "
+                    "facet.doc.txt=True")
+                self.pkg("change-variant --reject=nothing "
+                    "variant.icecream=neapolitan")
+
+                # Reset the facets/variant to the same value (which would
+                # normally be a noop) while rejecting a package and make sure
+                # that package gets uninstalled.
+                self.pkg("change-facet --reject=need_foo "
+                    "facet.doc.txt=True")
+                self.pkg("install [email protected]")
+                self.pkg("change-variant --reject=need_foo "
+                    "variant.icecream=neapolitan")
+                self.pkg("install [email protected]")
+
+                # Reset the facets/variant to the same value (which would
+                # normally be a noop) while rejecting a package we can't
+                # uninstall due to dependencies.  Make sure this fails.
+                self.pkg("change-facet --reject=foo "
+                    "facet.doc.txt=True", exit=EXIT_OOPS)
+                self.pkg("change-variant --reject=foo "
+                    "variant.icecream=neapolitan", exit=EXIT_OOPS)
+
+
+if __name__ == "__main__":
+        unittest.main()
--- a/src/tests/cli/t_pkg_verify.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkg_verify.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -98,6 +98,10 @@
                 # fatal.
                 self.pkg("verify foo")
 
+                # Should not output anything when using -q.
+                self.pkg("verify -q foo")
+                assert(self.output == "")
+
                 # Should not fail if publisher is disabled and package is ok.
                 self.pkg("set-publisher -d test")
                 self.pkg("verify foo")
--- a/src/tests/cli/t_pkgdep_resolve.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgdep_resolve.py	Wed Aug 14 11:12:35 2013 +0530
@@ -1116,7 +1116,9 @@
                                     "\n".join(
                                         [str(d) for d in pkg_deps[col_path]]))
                         d = pkg_deps[one_dep][0]
-                        self.assertEqual(d.attrs["fmri"], exp_pkg)
+                        self.assertEqual(d.attrs["fmri"], exp_pkg,
+                            "Expected dependency %s; found %s." % (exp_pkg,
+                                d.attrs["fmri"]))
 
                 col_path = self.make_manifest(self.collision_manf)
                 col_path_num_var = self.make_manifest(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_pkgdiff.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+import pkg5unittest
+
+import os
+import unittest
+
+class TestPkgRepo(pkg5unittest.SingleDepotTestCase):
+        # Cleanup after every test.
+        persistent_setup = False
+
+        stub1 = """
+            dir owner=root group=root mode=0755 path=etc
+            file tmp/empty mode=0555 owner=root group=bin path=/etc/empty
+            file tmp/truck1 mode=0444 owner=root group=bin path=/etc/trailer"""
+
+        stub2 = """
+            dir owner=root group=root mode=0755 path=etc
+            file tmp/empty mode=0555 owner=root group=bin path=/etc/empty
+            file tmp/truck1 mode=0444 owner=root group=bin path=/etc/ditch """
+
+        tree10 = """
+            set name=pkg.fmri [email protected],5.11-0:20110804T203458Z
+            set name=pkg.summary value="Leafy SPARC package" variant.arch=sparc
+            set name=pkg.summary value="Leafy i386 package" variant.arch=i386
+            set name=info.classification value=org.opensolaris.category.2008:System/Core
+            set name=variant.arch value=i386 value=sparc
+            file tmp/truck1 mode=0444 owner=root group=bin path=/etc/trailer"""
+
+        tree20 = """
+            set name=pkg.fmri [email protected],5.11-0:20120804T203458Z
+            set name=pkg.summary value="Leafy SPARC package" variant.arch=sparc
+            set name=pkg.summary value="Leafy i386 package" variant.arch=i386
+            set name=info.classification value=org.opensolaris.category.2008:System/Core
+            set name=variant.arch value=i386 value=sparc
+            dir owner=root group=root mode=0755 path=etc
+            file tmp/empty mode=0555 owner=root group=bin path=/etc/empty
+            file tmp/truck1 mode=0444 owner=root group=bin path=/etc/trailer"""
+
+        tree30 = """
+            set name=pkg.fmri [email protected],5.11-0:20130804T203458Z
+            set name=pkg.summary value="Leafy SPARC package" variant.arch=sparc
+            set name=pkg.summary value="Leafy i386 package" variant.arch=i386
+            set name=info.classification value=org.opensolaris.category.2008:System/Core
+            set name=variant.arch value=i386 value=sparc
+            dir owner=root group=root mode=0755 path=etc
+            file tmp/empty mode=0555 owner=root group=bin path=/etc/empty
+            file tmp/truck1 mode=0444 owner=root group=bin path=/etc/trailer"""
+
+        def setUp(self):
+                pkg5unittest.SingleDepotTestCase.setUp(self)
+                tfiles = self.make_misc_files(["tmp/empty", "tmp/truck1",
+                    "tmp/noaccess"])
+                self.stub1_p5m = self.make_manifest(self.stub1)
+                self.stub2_p5m = self.make_manifest(self.stub2)
+                self.tree10_p5m = self.make_manifest(self.tree10)
+                self.tree20_p5m = self.make_manifest(self.tree20)
+                self.tree30_p5m = self.make_manifest(self.tree30)
+                self.bogus_p5m = os.path.join(self.test_root, "nosuch.p5m")
+                self.noaccess_p5m = self.make_misc_files(
+                    ["tmp/noaccess.p5m"])[0]
+                os.chmod(self.noaccess_p5m, 0000)
+
+        def test_00_base(self):
+                """Verify pkgdiff handles basic option and subcommand parsing as
+                expected.
+                """
+
+                # --help, -? should exit with 0.
+                self.pkgdiff("--help", exit=0)
+                self.pkgdiff("'-?'", exit=0)
+
+                # unknown options should exit with 2.
+                self.pkgdiff("-U", exit=2)
+                self.pkgdiff("--unknown", exit=2)
+
+                # no arguments should exit with 2.
+                self.pkgdiff("", exit=2)
+
+                # one argument should exit with 2.
+                self.pkgdiff(self.tree10_p5m, exit=2)
+
+        def test_01_input(self):
+                """Verify that pkgdiff can accept input from both files and
+                stdin and works as expected."""
+
+                #
+                # Verify file input.
+                #
+
+                # Verify that pkgdiff finds no difference for the same file.
+                self.pkgdiff(" ".join((self.tree10_p5m, self.tree10_p5m)))
+
+                # Verify that pkgdiff finds a difference for different files.
+                self.pkgdiff(" ".join((self.tree10_p5m, self.tree20_p5m)),
+                    exit=1)
+
+                # Verify that pkgdiff gracefully handles no such file errors.
+                self.pkgdiff(" ".join((self.tree10_p5m, self.bogus_p5m)), exit=3)
+
+                # Verify that pkgdiff gracefully handles permission errors.
+                self.pkgdiff(" ".join((self.tree10_p5m, self.noaccess_p5m)),
+                    su_wrap=True, exit=3)
+
+                #
+                # Verify stdin input.
+                #
+
+                # Verify that both arguments cannot be stdin.
+                self.pkgdiff("- -", exit=2)
+
+                # Verify that one argument can be stdin with no differences for
+                # identical case.
+                self.pkgdiff("- %s < %s" % (self.tree10_p5m, self.tree10_p5m))
+
+                # Verify that one argument can be stdin with differences.
+                self.pkgdiff("%s - < %s" % (self.tree10_p5m, self.tree20_p5m),
+                    exit=1)
+
+        def test_02_type_filter(self):
+                """Verify that pkgdiff action type filtering works as expected."""
+
+                # Verify unknown types cause graceful failure.
+                self.pkgdiff(" ".join(("-t bogus,nosuchtype", self.tree10_p5m,
+                    self.tree10_p5m)), exit=2)
+                self.pkgdiff(" ".join(("-t bogus", "-t nosuchtype",
+                    self.tree10_p5m, self.tree10_p5m)), exit=2)
+                self.pkgdiff(" ".join(("-t bogus", "-t file", self.tree10_p5m,
+                    self.tree10_p5m)), exit=2)
+
+                # Verify no differences for same manifest.
+                self.pkgdiff(" ".join(("-t file", self.tree10_p5m,
+                    self.tree10_p5m)))
+
+                # Verify differences found for file actions between 1.0 and 2.0.
+                self.pkgdiff(" ".join(("-t file", self.tree10_p5m,
+                    self.tree20_p5m)), exit=1)
+
+                # Verify differences found for dir actions between 1.0 and 2.0.
+                self.pkgdiff(" ".join(("-t dir", self.tree10_p5m,
+                    self.tree20_p5m)), exit=1)
+
+                # Verify no differences found for file actions between 2.0 and
+                # 3.0.
+                self.pkgdiff(" ".join(("-t file", self.tree20_p5m,
+                    self.tree30_p5m)))
+
+                # Verify no differences found for dir and file actions between
+                # 2.0 and 3.0 using both option forms.
+                self.pkgdiff(" ".join(("-t dir,file", self.tree20_p5m,
+                    self.tree30_p5m)), stderr=True)
+
+                self.pkgdiff(" ".join(("-t dir", "-t file", self.tree20_p5m,
+                    self.tree30_p5m)))
+
+                # Verify differences found when only one action of a given type
+                # of two differs between stub1 and stub2 and other actions are
+                # the same.
+                self.pkgdiff(" ".join(("-t file", self.stub1_p5m,
+                    self.stub2_p5m)), exit=1)
+
+
+if __name__ == "__main__":
+        unittest.main()
--- a/src/tests/cli/t_pkgmerge.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgmerge.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -48,7 +48,7 @@
         persistent_setup = True
 
         scheme10 = """
-            open pkg:/[email protected],5.11-0
+            open [email protected],5.11-0
             add file tmp/sparc-only mode=0444 owner=root group=bin path=/etc/tree
             close
         """
@@ -201,9 +201,7 @@
             "tmp/sparc3", "tmp/sparc4", "tmp/i3861", "tmp/i3862", "tmp/i3863"]
 
         def setUp(self):
-                pkg5unittest.ManyDepotTestCase.setUp(self, ["os.org", "os.org",
-                    "os.org", "os.org", "os.org", "os.org", "os.org", "os.org",
-                    "os.org", "os.org", "os.org", "os.org", "os.org"])
+                pkg5unittest.ManyDepotTestCase.setUp(self, 16 * ["os.org"])
                 self.make_misc_files(self.misc_files)
 
                 self.rurl1 = self.dcs[1].get_repo_url()
@@ -223,6 +221,11 @@
                 self.rurl11 = self.dcs[11].get_repo_url()
                 self.rurl12 = self.dcs[12].get_repo_url()
                 self.rurl13 = self.dcs[13].get_repo_url()
+
+                # repositories which will contain several publishers
+                self.rurl14 = self.dcs[14].get_repo_url()
+                self.rurl15 = self.dcs[15].get_repo_url()
+
                 # Publish a set of packages to one repository.
                 self.published = self.pkgsend_bulk(self.rurl1, (self.amber10,
                     self.amber20, self.bronze10, self.bronze20, self.tree10,
@@ -285,6 +288,44 @@
                 time.sleep(1)
                 self.published_blend += self.pkgsend_bulk(self.rurl13, (self.multiD,))
 
+                # Publish to multiple repositories, maintaining lists of which
+                # FMRIs are published to which repository.
+                self.published_multi_14 = []
+                self.published_multi_15 = []
+
+                for url, record in [
+                    (self.rurl14, self.published_multi_14),
+                    (self.rurl15, self.published_multi_15)]:
+                        time.sleep(1)
+                        record += self.pkgsend_bulk(url, (self.scheme10))
+                        time.sleep(1)
+                        record += self.pkgsend_bulk(url, (self.tree10))
+
+                        time.sleep(1)
+                        record += self.pkgsend_bulk(url,
+                            self.bronze20.replace("open ",
+                            "open pkg://altpub/"))
+                        time.sleep(1)
+                        record += self.pkgsend_bulk(url,
+                            (self.amber10.replace("open ",
+                            "open pkg://altpub/")))
+                        time.sleep(1)
+                        record += self.pkgsend_bulk(url,
+                            (self.multiA.replace("open ",
+                            "open pkg://last/")))
+
+                # add bronze20b to one repository so that we have at least one
+                # package where more complex merging happens.
+                time.sleep(1)
+                self.published_multi_15 += self.pkgsend_bulk(self.rurl15,
+                    self.bronze20b.replace("open ", "open pkg://altpub/"))
+
+                # one of our source repositories also contains a newer
+                # version of pkg:/gold (self.multi*)
+                time.sleep(1)
+                self.published_multi_15 += self.pkgsend_bulk(self.rurl15,
+                    (self.multiB.replace("open ", "open pkg://last/")))
+
         def test_0_options(self):
                 """Verify that pkgmerge gracefully fails when given bad option
                 values."""
@@ -341,6 +382,12 @@
                     "-d %s" % self.test_root,
                 ]), exit=1)
 
+                # Should fail because of no matching -p publishers.
+                self.pkgmerge(" ".join([
+                    "-s arch=i386,%s" % self.rurl2,
+                    "-d %s -p noodles" % self.test_root,
+                ]), exit=1)
+
         def test_1_single_merge(self):
                 """Verify that merge functionality works as expected when
                 specifying a single source."""
@@ -992,13 +1039,215 @@
                 self.assertEqualDiff(expected, actual)
                 shutil.rmtree(repodir)
 
-        def get_manifest(self, repodir):
-                repo = self.get_repo(repodir)
-                cat = repo.get_catalog(pub="os.org")
-                for f in cat.fmris():
-                        with open(repo.manifest(f), "rb") as m:
-                                actual = "".join(sorted(l for l in m)).strip()
-                return actual
+        def test_7_multipub_merge(self):
+                """Tests that we can merge packages from repositories with
+                several publishers."""
+
+                repodir = os.path.join(self.test_root, "7merge_repo")
+                self.create_repo(repodir)
+
+                # test dry run
+                self.pkgmerge(" ".join([
+                    "-n",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]))
+
+                # test dry run with selected publishers
+                self.pkgmerge(" ".join([
+                    "-p os.org",
+                    "-p altpub",
+                    "-n",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]))
+
+                # this should fail, as no -p noodles publisher exists in any of
+                # the source repositories
+                self.pkgmerge(" ".join([
+                    "-p os.org",
+                    "-p altpub",
+                    "-p noodles",
+                    "-n",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]), exit=1)
+
+                # now we want to perform the merge operations and validate the
+                # results. This was the order we published packages to multi_15
+                # 0  = pkg://os.org/[email protected],5.11-0:20120920T085857Z
+                # 1  = pkg://os.org/[email protected],5.11-0:20120920T085859Z
+                # 2  = pkg://altpub/[email protected],5.11-0:20120920T085902Z
+                # 3  = pkg://altpub/[email protected],5.11-0:20120920T085904Z
+                # 4  = pkg://last/[email protected],5.11-0:20120920T085906Z
+                # 5  = pkg://altpub/[email protected],5.11-0:20120920T085920Z
+                # 6  = pkg://last/[email protected],5.11-0:20120920T085923Z
+
+                # build a dictionary of the FMRIs we're interested in
+                repo15_fmris = {
+                    "osorg_scheme": self.published_multi_15[0],
+                    "osorg_tree": self.published_multi_15[1],
+                    "altpub_amber": self.published_multi_15[3],
+                    # we published two versions of bronze and gold, use the
+                    # latest FMRI
+                    "altpub_bronze": self.published_multi_15[5],
+                    "last_gold": self.published_multi_15[6]
+                }
+
+                # the some expected manifests we should get after merging.
+                expected_osorg_scheme = """\
+file 3a06aa547ffe0186a2b9db55b8853874a048fb47 chash=ab50364de4ce8f847d765d402d80e37431e1f0aa group=bin mode=0444 owner=root path=etc/tree pkg.csize=40 pkg.size=20
+set name=pkg.fmri value=%(osorg_scheme)s
+set name=variant.arch value=sparc value=i386
+set name=variant.debug value=false\
+""" % repo15_fmris
+                expected_osorg_tree = """\
+file 3a06aa547ffe0186a2b9db55b8853874a048fb47 chash=ab50364de4ce8f847d765d402d80e37431e1f0aa group=bin mode=0444 owner=root path=etc/tree pkg.csize=40 pkg.size=20
+set name=pkg.fmri value=%(osorg_tree)s
+set name=variant.arch value=sparc value=i386
+set name=variant.debug value=false\
+""" % repo15_fmris
+                expected_altpub_amber = """\
+depend fmri=pkg:/[email protected] type=require
+set name=pkg.fmri value=%(altpub_amber)s
+set name=variant.arch value=sparc value=i386
+set name=variant.debug value=false\
+""" % repo15_fmris
+                expected_altpub_bronze = """\
+depend fmri=pkg:/[email protected] type=require
+depend fmri=pkg:/[email protected] type=require variant.arch=i386
+dir group=bin mode=0755 owner=root path=etc
+dir group=bin mode=0755 owner=root path=lib
+file 1abe1a7084720f501912eceb1312ddd799fb2a34 chash=ea7230676e13986491d7405c5a9298e074930575 group=bin mode=0444 owner=root path=etc/bronze1 pkg.csize=37 pkg.size=17
+file 34f88965d55d3a730fa7683bc0f370fc6e42bf95 chash=66eebb69ee0299dcb495162336db81a3188de037 group=bin mode=0555 owner=root path=usr/bin/sh pkg.csize=32 pkg.size=12
+file 6d8f3b9498aa3bbe7db01189b88f1b71f4ce40ad chash=6f3882864ebd7fd1a09e0e7b889fdc524c8c8bb2 group=bin mode=0444 owner=root path=etc/amber2 pkg.csize=37 pkg.size=17 variant.arch=sparc
+file 8535c15c49cbe1e7cb1a0bf8ff87e512abed66f8 chash=6ff2f52d2f894f5c71fb8fdd3b214e22959fccbb group=bin mode=0555 owner=root path=lib/libc.bronze pkg.csize=33 pkg.size=13
+file 91fa26695f9891b2d94fd72c31b640efb5589da5 chash=4eed1e5dc5ab131812da34dc148562e6833fa92b group=bin mode=0444 owner=root path=etc/scheme pkg.csize=36 pkg.size=16 variant.arch=i386
+file cf68b26a90cb9a0d7510f24cfb8cf6d901cec34e chash=0eb6fe69c4492f801c35dcc9175d55f783cc64a2 group=bin mode=0444 owner=root path=A1/B2/C3/D4/E5/F6/bronzeA2 pkg.csize=38 pkg.size=18
+hardlink path=lib/libc.bronze2.0.hardlink target=/lib/libc.so.1
+license 773b94a252723da43e8f969b4384701bcd41ce12 chash=e0715301fc211f6543ce0c444f4c34e38c70f70e license=copyright pkg.csize=40 pkg.size=20
+link path=usr/bin/jsh target=./sh
+set name=pkg.fmri value=%(altpub_bronze)s
+set name=variant.arch value=sparc value=i386
+set name=variant.debug value=false\
+""" % repo15_fmris
+                expected_last_gold = """\
+depend fmri=foo fmri=bar type=require-any
+file 6b7161cb29262ea4924a8874818da189bb70da09 chash=77e271370cec04931346c969a85d6af37c1ea83f group=bin mode=0444 owner=root path=etc/binary pkg.csize=36 pkg.size=16 variant.arch=i386
+file 6b7161cb29262ea4924a8874818da189bb70da09 chash=77e271370cec04931346c969a85d6af37c1ea83f group=bin mode=0444 owner=root path=etc/everywhere-notes pkg.csize=36 pkg.size=16
+file 9e837a70edd530a88c88f8a58b8a5bf2a8f3943c chash=d0323533586e1153bd1701254f45d2eb2c7eb0c4 group=bin mode=0444 owner=root path=etc/debug-notes pkg.csize=36 pkg.size=16
+file a10f11b8559a723bea9ee0cf5980811a9d51afbb chash=9fb8079898da8a2a9faad65c8df4c4a42095f25a group=bin mode=0444 owner=root path=etc/sparc/debug-notes pkg.csize=36 pkg.size=16 variant.arch=sparc
+file aab699c6424ed1fc258b6b39eb113e624a9ee368 chash=43c3b9a83a112727264390002c3db3fcebec2e76 group=bin mode=0444 owner=root path=etc/binary pkg.csize=36 pkg.size=16 variant.arch=sparc
+set name=pkg.fmri value=%(last_gold)s
+set name=variant.arch value=sparc value=i386
+set name=variant.debug value=false\
+""" % repo15_fmris
+
+                # A dictionary of the expected package contents, keyed by FMRI
+                expected = {
+                    repo15_fmris["altpub_bronze"]: expected_altpub_bronze,
+                    repo15_fmris["altpub_amber"]: expected_altpub_amber,
+                    repo15_fmris["osorg_tree"]: expected_osorg_tree,
+                    repo15_fmris["osorg_scheme"]: expected_osorg_scheme,
+                    repo15_fmris["last_gold"]: expected_last_gold
+                }
+
+                def check_repo(repodir, keys, fmri_dic, expected):
+                        """Check that packages corresponding to the list of
+                        keys 'keys' to items in 'fmri_dic' are present in the
+                        repository, and match the contents from the dictionary
+                        'expected'.  We also check that the repository has no
+                        packages other than those specified by 'keys', and no
+                        more publishers than are present in those packages."""
+                        sr = self.get_repo(repodir)
+                        # check that the packages from 'keys' exist,
+                        # and their content matches what we expect.
+                        for key in keys:
+                                f = fmri_dic[key]
+                                with open(sr.manifest(f), "rb") as manf:
+                                        actual = "".join(
+                                            sorted(l for l in manf)).strip()
+                                self.assertEqualDiff(expected[f], actual)
+
+                        # check that we have only the publishers used
+                        # by packages from 'keys' in the repository
+                        fmris = [fmri_dic[key] for key in keys]
+                        pubs = set([fmri.PkgFmri(entry).get_publisher()
+                            for entry in fmris])
+                        known_pubs = set(
+                            [p.prefix for p in sr.get_publishers()])
+                        self.assert_(pubs == known_pubs,
+                            "Repository at %s didn't contain the "
+                            "expected set of publishers")
+
+                        # check that we have only the packages defined
+                        # in 'keys' in the repository by walking all
+                        # publishers, and all packages in the repository
+                        for pub in sr.get_publishers():
+                                cat = sr.get_catalog(pub=p.prefix)
+                                for f in cat.fmris():
+                                        if f.get_fmri() not in fmris:
+                                                self.assert_(False,
+                                                    "%s not in repository" % f)
+
+                # test merging all publishers.
+                self.pkgmerge(" ".join([
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]))
+
+                check_repo(repodir, repo15_fmris.keys(), repo15_fmris, expected)
+
+                # test merging only altpub and os.org.
+                shutil.rmtree(repodir)
+                self.create_repo(repodir)
+                self.pkgmerge(" ".join([
+                    "-p altpub",
+                    "-p os.org",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]))
+
+                check_repo(repodir, ["altpub_bronze", "altpub_amber",
+                    "osorg_tree", "osorg_scheme"], repo15_fmris, expected)
+
+                # test merging only altpub
+                shutil.rmtree(repodir)
+                self.create_repo(repodir)
+                self.pkgmerge(" ".join([
+                    "-p altpub",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]))
+
+                check_repo(repodir, ["altpub_bronze", "altpub_amber"],
+                    repo15_fmris, expected)
+
+                # this should exit with a 1, but we should get the same results
+                # in the repository as last time.
+                shutil.rmtree(repodir)
+                self.create_repo(repodir)
+                self.pkgmerge(" ".join([
+                    "-p altpub",
+                    "-p noodles",
+                    "-s arch=sparc,debug=false,%s" % self.dcs[14].get_repodir(),
+                    "-s arch=i386,debug=false,%s" % self.dcs[15].get_repodir(),
+                    "-d %s" % repodir]), exit=1)
+
+                check_repo(repodir, ["altpub_bronze", "altpub_amber"],
+                    repo15_fmris, expected)
+
+        def get_manifest(self, repodir, pubs=["os.org"]):
+                repository = self.get_repo(repodir)
+                actual = ""
+                for pub in pubs:
+                        cat = repository.get_catalog(pub=pub)
+                        for f in cat.fmris():
+                                with open(repository.manifest(f), "rb") as m:
+                                        actual += "".join(
+                                            sorted(l for l in m)).strip()
+                        actual += "\n"
+                return actual.strip()
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgmogrify.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgmogrify.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -142,6 +142,7 @@
             "bredit2": "<transform file path=usr/share/locale/([^/]+).* -> edit path %%<1> LANG>",
             "edit1": "<transform file path=usr/(share|lib)/locale.* -> edit path usr/(lib|share)/locale place/\\\\1/langs>",
             "doublequote": "<transform legacy -> default name %%{pkg.summary}>",
+            "delete-with-no-operand": "<transform file -> delete >",
         }
 
         basic_defines = {
@@ -288,6 +289,8 @@
 
                 self.pkgmogrify([self.transforms["drop mode=0755"], source_file])
                 self.assertNoMatch("^file.*mode=0755")
+                self.pkgmogrify([self.transforms["delete-with-no-operand"],
+                    source_file], exit=1)
 
         def test_4(self):
                 source_file = os.path.join(self.test_root, "source_file")
--- a/src/tests/cli/t_pkgrecv.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgrecv.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -40,6 +40,7 @@
 import pkg.portable as portable
 import pkg.server.repository as repo
 import shutil
+import subprocess
 import tempfile
 import time
 import urllib
@@ -53,13 +54,13 @@
 
         scheme10 = """
             open pkg:/[email protected],5.11-0
-            close 
+            close
         """
 
         tree10 = """
             open [email protected],5.11-0
             add depend type=require-any [email protected] [email protected]
-            close 
+            close
         """
 
         leaf10 = """
@@ -75,13 +76,19 @@
         amber10 = """
             open [email protected],5.11-0
             add depend fmri=pkg:/[email protected] type=require
-            close 
+            close
         """
 
         amber20 = """
             open [email protected],5.11-0
             add depend fmri=pkg:/[email protected] type=require
-            close 
+            close
+        """
+
+        amber30 = """
+            open [email protected],5.11-0
+            add depend fmri=pkg:/[email protected] type=require
+            close
         """
 
         bronze10 = """
@@ -112,7 +119,7 @@
             add license tmp/copyright3 license=copyright
             add file tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
             add depend fmri=pkg:/[email protected] type=require
-            close 
+            close
         """
 
         misc_files = [ "tmp/bronzeA1",  "tmp/bronzeA2", "tmp/bronze1",
@@ -458,6 +465,48 @@
                             "manifest")
                         self.assertTrue(os.path.isfile(mpath))
 
+                # Cleanup for next test.
+                shutil.rmtree(os.path.join(self.tempdir, "bronze"))
+
+                # Retrieve bronze using -m latest, this should only
+                # retrieve bronze20_2.
+                self.pkgrecv(self.durl1, "--raw -m latest -r -k "
+                    "-d %s %s" % (self.tempdir, "bronze"))
+
+                # Verify that only expected packages were retrieved.
+                expected = [
+                    bronze20_2.get_dir_path(),
+                ]
+
+                for d in os.listdir(os.path.join(self.tempdir, "bronze")):
+                        self.assertTrue(os.path.join("bronze", d) in expected)
+
+                        mpath = os.path.join(self.tempdir, "bronze", d,
+                            "manifest")
+                        self.assertTrue(os.path.isfile(mpath))
+
+                # Cleanup for next test.
+                shutil.rmtree(os.path.join(self.tempdir, "bronze"))
+
+                # Retrieve bronze using default setting.
+                # This should retrieve bronze10, bronze20_1, and bronze20_2.
+                self.pkgrecv(self.durl1, "--raw -r -k "
+                    "-d %s %s" % (self.tempdir, "bronze"))
+
+                # Verify that all expected packages were retrieved.
+                expected = [
+                    bronze10.get_dir_path(),
+                    bronze20_1.get_dir_path(),
+                    bronze20_2.get_dir_path(),
+                ]
+
+                for d in expected:
+                        paths = os.listdir(os.path.join(self.tempdir, "bronze"))
+                        self.assertTrue(os.path.basename(d) in paths)
+
+                        mpath = os.path.join(self.tempdir, d, "manifest")
+                        self.assertTrue(os.path.isfile(mpath))
+
         def test_5_recv_env(self):
                 """Verify that pkgrecv environment vars work as expected."""
 
@@ -660,6 +709,9 @@
                 self.pkgrecv(self.durl1, "-r -n -d %s %s" % (rpth, f))
                 self.assertEqualDiff(expected, os.listdir(rpth))
 
+                self.pkgrecv(self.durl1, "--clone -n -p '*' -d %s" % (rpth))
+                self.assertEqualDiff(expected, os.listdir(rpth))
+
                 arc_path = os.path.join(self.test_root, "test.p5p")
                 self.pkgrecv(self.durl1, "-a -n -d %s \*" % arc_path)
                 self.assert_(not os.path.exists(arc_path))
@@ -709,9 +761,10 @@
                         # otherwise pkgrecv will fail because the manifest
                         # doesn't validate.
 
+                        novalidate = "-D manifest_validate=Never "
                         # Check that invalid action attributes don't cause
                         # tracebacks.
-                        self.pkgrecv(self.durl1, "-D manifest_validation=False "
+                        self.pkgrecv(self.durl1, novalidate +
                             "-d %s %s %s" % (duri, arg_string,
                             " ".join(pfmris)), exit=pkgdefs.EXIT_OOPS)
                         for pfmri in pfmris:
@@ -720,7 +773,7 @@
                         if arg_string:
                                 portable.remove(duri)
 
-                        self.pkgrecv(self.rurl1, "-D manifest_validation=False "
+                        self.pkgrecv(self.rurl1, novalidate +
                             "-d %s %s %s" % (duri, arg_string,
                             " ".join(pfmris)), exit=pkgdefs.EXIT_OOPS)
                         for pfmri in pfmris:
@@ -731,7 +784,7 @@
 
                         # Check that other packages are retrieved and the exit
                         # code reflects partial success.
-                        self.pkgrecv(self.durl1, "-D manifest_validation=False "
+                        self.pkgrecv(self.durl1, novalidate +
                             "-d %s %s -m all-timestamps '*'" %
                             (duri, arg_string), exit=pkgdefs.EXIT_PARTIAL)
                         for pfmri in pfmris:
@@ -740,7 +793,7 @@
                             len(self.published) - len(pfmris))
                         __empty_repo(duri, arg_string)
 
-                        self.pkgrecv(self.rurl1, "-D manifest_validation=False "
+                        self.pkgrecv(self.rurl1, novalidate +
                             "-d %s %s -m all-timestamps '*'" %
                             (duri, arg_string), exit=pkgdefs.EXIT_PARTIAL)
                         for pfmri in pfmris:
@@ -785,6 +838,207 @@
                 for duri, arg_string, in dest_uris:
                         __test_rec(duri, arg_string, self.published[4:7])
 
+        def test_11_clone(self):
+                """Verify that pkgrecv handles cloning repos as expected."""
+                # Test basic operation of cloning repo which contains one
+                # publisher to repo which contains same publisher
+                self.pkgrecv(self.durl1, "--clone -d %s" % self.dpath2)
+                
+                ret = subprocess.call(["/usr/bin/gdiff", "-Naur", "-x", 
+                    "index", "-x", "trans", self.dpath1, self.dpath2])
+                self.assertTrue(ret==0)
+
+                # Test that packages in dst which are not in src get removed.
+                self.pkgsend_bulk(self.durl2, (self.amber30))
+                self.pkgrecv(self.durl1, "--clone -d %s" % self.dpath2)
+                ret = subprocess.call(["/usr/bin/gdiff", "-Naur", "-x", 
+                    "index", "-x", "trans", self.dpath1, self.dpath2])
+                self.assertTrue(ret==0)
+
+                # Test that clone reports publishers not in the dest repo.
+                amber = self.amber10.replace("open ", "open pkg://test2/")
+                self.pkgsend_bulk(self.durl1, amber)
+                self.pkgrecv(self.durl1, "--clone -d %s" % self.dpath2, exit=1)
+
+                # Test that clone adds new publishers if requested.
+                # Note: adding a publisher will automatically create a pub.p5i
+                # in the repo store. Since that is repo configuration and not
+                # part of the cloning it is ignored.
+                amber = self.amber10.replace("open ", "open pkg://test2/")
+                self.pkgsend_bulk(self.durl1, amber)
+                self.pkgrecv(self.durl1, "--clone -d %s -p test2" % self.dpath2)
+                ret = subprocess.call(["/usr/bin/gdiff", "-Naur", "-x", 
+                    "index", "-x", "trans", "-x", "pub.p5i", self.dpath1,
+                    self.dpath2])
+                self.assertTrue(ret==0)
+
+                # Test that clone removes all packages if source is empty
+                self.pkgrecv(self.durl3, "--clone -d %s" % self.dpath2)
+                self.pkgrepo("-s %s list -H -p test2" % self.dpath2)
+                self.assertEqualDiff("", self.output)
+
+                # Test that clone fails if --raw is specified.
+                self.pkgrecv(self.durl1, "--raw --clone -d %s -p test2" %
+                    self.dpath2, exit=2)
+                
+                # Test that clone fails if -c is specified.
+                self.pkgrecv(self.durl1, "-c /tmp/ --clone -d %s -p test2" %
+                    self.dpath2, exit=2)
+
+                # Test that clone fails if -a is specified.
+                self.pkgrecv(self.durl1, "-a --clone -d %s -p test2" %
+                    self.dpath2, exit=2)
+
+                # Test that clone fails if --newest is specified.
+                self.pkgrecv(self.durl1, "--newest --clone -d %s -p test2" %
+                    self.dpath2, exit=2)
+
+
+class TestPkgrecvHTTPS(pkg5unittest.HTTPSTestClass):
+
+        example_pkg10 = """
+            open [email protected],5.11-0
+            add file tmp/example_file mode=0555 owner=root group=bin path=/usr/bin/example_path
+            close"""
+
+        misc_files = ["tmp/example_file", "tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pubs = ["src", "dst"]
+
+                pkg5unittest.HTTPSTestClass.setUp(self, pubs,
+                    start_depots=True)
+                
+                self.srurl = self.dcs[1].get_repo_url()
+                self.make_misc_files(self.misc_files)
+                self.pkgsend_bulk(self.srurl, self.example_pkg10)
+
+                self.surl = self.ac.url + "/%s" % pubs[0]
+                self.durl = self.ac.url + "/%s" % pubs[1]
+
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+                
+
+        def test_01_basics(self):
+                """Test that transfering a package from an https repo to
+                another https repo works"""
+
+                self.ac.start()
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("src")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("src")),
+                    "dst": self.durl,
+                    "dcert": os.path.join(self.cs_dir, self.get_cli_cert("dst")),
+                    "dkey": os.path.join(self.keys_dir, self.get_cli_key("dst")),
+                    "pkg": "[email protected],5.11-0",
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # We try to receive a pkg from a secured repo and publish it to
+                # another secured repo where both repos require different
+                # credentials
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict)
+
+                # Now try to use the same credentials for source and dest.
+                # This should fail.
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(key)s --dcert %(cert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Src certificate option missing
+                self.pkgrecv(self.surl, "--key %(key)s -d %(dst)s "
+                    "--dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate option missing
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key option missing
+                self.pkgrecv(self.surl, "--cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key option missing
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src certificate not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(noexist)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(noexist)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key not found
+                self.pkgrecv(self.surl, "--key %(noexist)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(noexist)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src certificate is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(empty)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(empty)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key is empty file
+                self.pkgrecv(self.surl, "--key %(empty)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(empty)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+                
+                # No permissions to read src certificate 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(verboten)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read dst certificate 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(verboten)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read src key 
+                self.pkgrecv(self.surl, "--key %(verboten)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read dst key 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(verboten)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
 
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgrepo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgrepo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -2161,5 +2161,113 @@
                 self.assert_("no matching publishers" in self.errout)
 
 
+class TestPkgrepoHTTPS(pkg5unittest.HTTPSTestClass):
+
+        example_pkg10 = """
+            open [email protected],5.11-0
+            add file tmp/example_file mode=0555 owner=root group=bin path=/usr/bin/example_path
+            close"""
+
+        misc_files = ["tmp/example_file", "tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pub = "test"
+
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub],
+                    start_depots=True)
+                
+                self.url = self.ac.url + "/%s" % pub
+
+                # publish a simple test package
+                self.srurl = self.dcs[1].get_repo_url()
+                self.make_misc_files(self.misc_files)
+                self.pkgsend_bulk(self.srurl, self.example_pkg10)
+
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+                
+
+        def test_01_basics(self):
+                """Test that running pkgrepo on an SSL-secured repo works for
+                all operations which are valid for network repos"""
+
+                self.ac.start()
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir,
+                    self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir,
+                    self.get_cli_key("test")),
+                    "url": self.url,
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # Try all pkgrepo operations which are valid for network repos.
+                # pkgrepo info
+                self.pkgrepo("-s %(url)s info --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo list
+                self.pkgrepo("-s %(url)s list --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo get
+                self.pkgrepo("-s %(url)s get --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo refresh
+                self.pkgrepo("-s %(url)s refresh --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo rebuild
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # Try without key and cert (should fail)
+                self.pkgrepo("-s %(url)s rebuild" % arg_dict, exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Certificate option missing
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s" % arg_dict,
+                    exit=1)
+
+                # Key option missing
+                self.pkgrepo("-s %(url)s rebuild --cert %(cert)s" % arg_dict,
+                    exit=1)
+
+                # Certificate not found
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(noexist)s" % arg_dict, exit=1)
+
+                # Key not found
+                self.pkgrepo("-s %(url)s rebuild --key %(noexist)s "
+                    "--cert %(cert)s" % arg_dict, exit=1)
+
+                # Certificate is empty file
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(empty)s" % arg_dict, exit=1)
+
+                # Key is empty file
+                self.pkgrepo("-s %(url)s rebuild --key %(empty)s "
+                    "--cert %(cert)s" % arg_dict, exit=1)
+
+                # No permissions to read certificate 
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(verboten)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read key 
+                self.pkgrepo("-s %(url)s rebuild --key %(verboten)s "
+                    "--cert %(cert)s" % arg_dict, su_wrap=True, exit=1)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgsend.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgsend.py	Wed Aug 14 11:12:35 2013 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -1407,5 +1407,101 @@
                 do_test("d1/f1", "d1/f2", "d2/f3")
 
 
+class TestPkgsendHTTPS(pkg5unittest.HTTPSTestClass):
+
+        misc_files = ["tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pub = "test"
+
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub],
+                    start_depots=True)
+
+                self.url = self.ac.url + "/%s" % pub
+                self.make_misc_files(self.misc_files)
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+
+        def test_01_basics(self):
+                """Test that publishing to an SSL-secured repo works"""
+
+                self.ac.start()
+
+                rootdir = self.test_root
+                dir_1 = os.path.join(rootdir, "dir_1")
+                os.mkdir(dir_1)
+                file(os.path.join(dir_1, "A"), "wb").close()
+                file(os.path.join(dir_1, "B"), "wb").close()
+                mfpath = os.path.join(rootdir, "manifest_test")
+                with open(mfpath, "wb") as mf:
+                        mf.write("""file NOHASH mode=0755 owner=root group=bin path=/A
+                            file NOHASH mode=0755 owner=root group=bin path=/B
+                            set name=pkg.fmri [email protected],5.10
+                            """)
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    "url": self.url,
+                    "dir": dir_1,
+                    "mani": mfpath,
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # Try to publish a simple package to SSL-secured repo  
+                self.pkgsend(self.url, "publish --key %(key)s --cert %(cert)s "
+                    "-d %(dir)s %(mani)s" % arg_dict)
+        
+                # Try to publish a simple package to SSL-secured repo without
+                # prvoviding certs (should fail).  
+                self.pkgsend(self.url, "publish -d %(dir)s %(mani)s" % arg_dict,
+                    exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Certificate option missing
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key option missing
+                self.pkgsend(self.url, "publish --cert %(cert)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Certificate not found
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "--cert %(noexist)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key not found
+                self.pkgsend(self.url, "publish --key %(noexist)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Certificate is empty file
+                self.pkgsend(self.url, "publish --key %(key)s --cert %(empty)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key is empty file
+                self.pkgsend(self.url, "publish --key %(empty)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # No permissions to read certificate 
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "--cert %(verboten)s -d %(dir)s %(mani)s" % arg_dict,
+                    su_wrap=True, exit=1)
+
+                # No permissions to read key 
+                self.pkgsend(self.url, "publish --key %(verboten)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict,
+                    su_wrap=True, exit=1)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgsign.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_pkgsign.py	Wed Aug 14 11:12:35 2013 +0530
@@ -968,7 +968,7 @@
                 s += "\nset name=foo value=bar"
                 self.write_img_manifest(pfmri, s)
 
-                DebugValues["skip-verify-manifest"] = "True"
+                DebugValues["manifest_validate"] = "Never"
                 
                 self.pkg("set-property signature-policy verify")
                 # This should fail because the text of manifest has changed
@@ -1025,7 +1025,7 @@
                 s = s.replace("rsa-sha256", "rsa-foobar")
                 self.write_img_manifest(pfmri, s)
 
-                DebugValues["skip-verify-manifest"] = "True"
+                DebugValues["manifest_validate"] = "Never"
 
                 self.pkg("set-property signature-policy require-signatures")
                 api_obj = self.get_img_api_obj()
@@ -1051,7 +1051,7 @@
                 api_obj = self.get_img_api_obj()
                 self.assertRaises(apx.RequiredSignaturePolicyException,
                     self._api_install, api_obj, ["example_pkg"])
-                self.pkg("--debug skip-verify-manifest=True install "
+                self.pkg("--debug manifest_validate=Never install "
                     "example_pkg", exit=1)
                 # This passes because 'foobar' isn't a recognized signature
                 # algorithm so the signature action is skipped.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_pkgsurf.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,723 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+import testutils
+if __name__ == "__main__":
+        testutils.setup_environment("../../../proto")
+import pkg5unittest
+
+import os
+import pkg.catalog as catalog
+import pkg.config as cfg
+import pkg.client.pkgdefs as pkgdefs
+import pkg.fmri as fmri
+import pkg.manifest as manifest
+import pkg.misc as misc
+import pkg.p5p as p5p
+import pkg.portable as portable
+import pkg.server.repository as repo
+import shutil
+import subprocess
+import tempfile
+import time
+import urllib
+import urlparse
+import unittest
+import zlib
+
+class TestPkgsurf(pkg5unittest.ManyDepotTestCase):
+        # Cleanup after every test.
+        persistent_setup = True
+
+        # The 1.0 version of each package will be in the reference repo,
+        # the 2.0 version in the target.
+        # Since we publish the expected package to an additional repo, we have
+        # to set the timestamps to make sure the target and expected packages
+        # are equal.
+        
+        # The test cases are mainly in the different types of packages we
+        # have in the repo.
+
+        # Test cases:
+
+        # Pkg with no content change, should be reversioned.
+        # Pkg has all sorts of actions to make sure everything gets moved
+        # correctly.
+        tiger_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/bat
+            add dir mode=0755 owner=root group=bin path=/usr/tiger
+            add file tmp/sting mode=0444 owner=root group=bin path=/usr/tiger/sting
+            add link path=/usr/tiger/sting target=./stinger
+            add hardlink path=/etc/bat target=/usr/tiger/bat
+            add license tmp/copyright license=copyright
+            add user username=Tiger group=galeocerdones home-dir=/export/home/Tiger
+            add group groupname=galeocerdones gid=123
+            close
+        """
+
+        tiger_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/bat
+            add dir mode=0755 owner=root group=bin path=/usr/tiger
+            add file tmp/sting mode=0444 owner=root group=bin path=/usr/tiger/sting
+            add link path=/usr/tiger/sting target=./stinger
+            add hardlink path=/etc/bat target=/usr/tiger/bat
+            add license tmp/copyright license=copyright
+            add user username=Tiger group=galeocerdones home-dir=/export/home/Tiger
+            add group groupname=galeocerdones gid=123
+            close
+        """
+
+        tiger_exp = tiger_ref
+
+        # Another basic pkg which gets reversioned
+        sandtiger_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/sandtiger
+        """
+
+        sandtiger_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/sandtiger
+        """
+
+        sandtiger_exp = sandtiger_ref
+
+        # Basic package with content change, should not be reversioned.
+        hammerhead_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/hammerhead
+            close
+        """
+
+        hammerhead_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/hammerhead
+            close
+        """
+
+        hammerhead_exp = hammerhead_targ
+
+        # Package has only dep change but dependency package changed, 
+        # should not be reversioned.
+        blue_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        blue_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        blue_exp = blue_targ
+
+        # Same as above but let's try an additional level in the dep chain.
+        bull_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        bull_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        bull_exp = bull_targ
+        
+        # Package has only dep change and dependency package didn't change,
+        # should be reversioned.
+        mako_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        mako_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        mako_exp = mako_ref
+
+        # Same as above but let's try an additional level in the dep chain.
+        white_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        white_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        white_exp = white_ref
+
+        # Package has content change but depends on package which got reversioned,
+        # dependencies should be fixed.
+        # Pkg has all sorts of actions to make sure everything gets moved
+        # correctly.
+        
+        angel_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/angel
+            add dir mode=0755 owner=root group=bin path=/usr/angel
+            add file tmp/sting mode=0444 owner=root group=bin path=/usr/angel/sting
+            add link path=/usr/angel/sting target=./stinger
+            add hardlink path=/etc/bat target=/usr/angel/bat
+            add license tmp/copyright license=copyright
+            add user username=Angel group=squatinae home-dir=/export/home/Angel
+            add group groupname=squatinae gid=123
+            add depend fmri=pkg:/[email protected] type=require
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        angel_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/angel
+            add dir mode=0755 owner=root group=bin path=/usr/angel
+            add file tmp/sting mode=0444 owner=root group=bin path=/usr/angel/sting
+            add link path=/usr/angel/sting target=./stinger
+            add hardlink path=/etc/bat target=/usr/angel/bat
+            add license tmp/copyright license=copyright
+            add user username=Angel group=squatinae home-dir=/export/home/Angel
+            add group groupname=squatinae gid=123
+            add depend fmri=pkg:/[email protected] type=require
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        angel_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/angel
+            add dir mode=0755 owner=root group=bin path=/usr/angel
+            add file tmp/sting mode=0444 owner=root group=bin path=/usr/angel/sting
+            add link path=/usr/angel/sting target=./stinger
+            add hardlink path=/etc/bat target=/usr/angel/bat
+            add license tmp/copyright license=copyright
+            add user username=Angel group=squatinae home-dir=/export/home/Angel
+            add group groupname=squatinae gid=123
+            add depend fmri=pkg:/[email protected] type=require
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        # Package has content change and depends on package which didn't get
+        # reversioned, shouldn't be touched.
+        
+        horn_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/horn
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        horn_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/horn
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        horn_exp = horn_targ
+
+
+        # Package has content change but has require-any dep on package which 
+        # got reversioned, dependencies should be fixed.
+        
+        lemon_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/lemon
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        lemon_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/lemon
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        lemon_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/lemon
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        # Package has content change but has require-any dep on package which
+        # got reversioned, however, the require-any dependency wasn't in the old
+        # version. The version of the pkg in the ref repo should be substituted
+        # for tiger but not for sandtiger (since dep pkg is still successor of
+        # dep FMRI).
+        
+        leopard_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/leopard
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        leopard_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/leopard
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        leopard_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/leopard
+            add depend fmri=pkg:/[email protected] fmri=pkg:/[email protected] fmri=pkg:/[email protected] fmri=pkg:/[email protected] type=require-any
+            close
+        """
+
+        # Package has no content change but dependency stem changed, should
+        # always be treated as content change.
+        blacktip_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        blacktip_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        blacktip_exp = blacktip_targ
+
+        # Package has no content change but dependency got added, should
+        # always be treated as content change, other dependencies should be
+        # adjusted.
+        whitetip_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        whitetip_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        whitetip_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/[email protected] type=require
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        # Package has no content change but a change in an attribute,
+        # should be treated as content change by default but reversioned if
+        # proper CLI options are given (goblin_exp is just for the default
+        # behavior, gets modified in actual test case) 
+
+        goblin_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add set name=info.home value="deep sea" 
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/goblin
+            close
+        """
+
+        goblin_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add set name=info.home value="deeper sea" 
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/goblin
+            close
+        """
+
+        goblin_exp = goblin_targ
+
+        # Package only found in target, not in ref, with dependency on
+        # reversioned package. Dependency should be fixed.
+        reef_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/reef
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        reef_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/reef
+            add depend fmri=pkg:/[email protected] type=require
+            close
+        """
+
+        # Package is exactly the same as in ref repo, shouldn't be touched
+        sandbar_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/sandbar
+            close
+        """
+
+        sandbar_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/sandbar
+            close
+        """
+
+        sandbar_exp = sandbar_ref
+
+        # Packages with circular dependency and no change in dep chain.
+        greenland_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend [email protected] type=require
+            close
+        """
+
+        greenland_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend [email protected] type=require
+            close
+        """
+
+        greenland_exp = greenland_ref
+
+        sleeper_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend [email protected] type=require
+            close
+        """
+        sleeper_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend [email protected] type=require
+            close
+        """
+
+        sleeper_exp = sleeper_ref    
+
+
+        # Check for correct handling of Varcets. Pkg contains same dep FMRI stem
+        # twice. It also covers the case where a facet changes and the tool has
+        # to sustitute the version in the ref repo (sandtiger case).
+        whale_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0444 owner=root group=bin path=/etc/whale
+            add depend fmri=pkg:/[email protected] facet.version-lock=True type=require
+            add depend fmri=pkg:/tiger type=require
+            add depend fmri=pkg:/[email protected] facet.version-lock=False type=require
+            close
+        """
+
+        whale_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/whale
+            add depend fmri=pkg:/[email protected] facet.version-lock=True type=require
+            add depend fmri=pkg:/tiger type=require
+            add depend fmri=pkg:/[email protected] facet.version-lock=True type=require
+            close
+        """
+
+        whale_exp = """
+            open [email protected],5.11-0:20000101T000000Z
+            add file tmp/bat mode=0644 owner=root group=bin path=/etc/whale
+            add depend fmri=pkg:/[email protected] facet.version-lock=True type=require
+            add depend fmri=pkg:/tiger type=require
+            add depend fmri=pkg:/[email protected] facet.version-lock=True type=require
+            close
+        """
+
+        # Pkg in ref repo is newer than the one in target.
+        # Should not be reversioned. 
+        thresher_ref = """
+            open [email protected],5.11-0:20000101T000000Z
+            close
+        """
+
+        thresher_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            close
+        """
+
+        thresher_exp = thresher_targ
+
+        # Package only found in target, not in ref.
+        # Package has a dep on a reversioned pkg, but the reversioned pkg is 
+        # still a successor of the dep FMRI.
+        # The dep should not be changed.
+        bamboo_targ = """
+            open [email protected],5.11-0:20000101T000000Z
+            add depend fmri=pkg:/tiger@1 type=require
+            close
+        """
+
+        bamboo_exp = bamboo_targ
+        
+
+        # Create some packages for an additional publisher
+        humpback_targ = """
+            open pkg://cetacea/[email protected],5.11-0:20000101T000000Z
+            close
+        """
+
+        humpback_ref = """                                                     
+            open pkg://cetacea/[email protected],5.11-0:20000101T000000Z             
+            close                                                               
+        """                                                                     
+
+        humpback_exp = humpback_targ
+
+
+        misc_files = [ "tmp/bat", "tmp/sting", "tmp/copyright" ]
+
+        pkgs = ["tiger", "sandtiger", "hammerhead", "blue", "bull", "mako",
+            "white", "angel", "horn", "lemon", "leopard", "blacktip",
+            "whitetip", "goblin", "reef", "sandbar", "greenland", "sleeper",
+            "whale", "thresher", "bamboo"]
+
+        def setUp(self):
+                """Start 3 depots, 1 for reference repo, 1 for the target and
+                1 which should be equal to the reversioned target.
+                """
+
+                self.ref_pkgs = []
+                self.targ_pkgs = []
+                self.exp_pkgs = []
+                for s in self.pkgs:
+                        ref = s + "_ref"
+                        targ = s + "_targ"
+                        exp = s + "_exp"
+                        try:
+                                self.ref_pkgs.append(getattr(self, ref))
+                        except AttributeError:
+                                # reef_ref, bamboo_ref don't exist intentionally
+                                pass
+                        self.targ_pkgs.append(getattr(self, targ))
+                        self.exp_pkgs.append(getattr(self, exp))
+                        
+                pkg5unittest.ManyDepotTestCase.setUp(self, ["selachii",
+                    "selachii", "selachii", "selachii"], start_depots=True)
+
+                self.make_misc_files(self.misc_files)
+
+                self.dpath1 = self.dcs[1].get_repodir()
+                self.durl1 = self.dcs[1].get_depot_url()
+                self.published_ref = self.pkgsend_bulk(self.dpath1,
+                    self.ref_pkgs)
+
+                self.dpath2 = self.dcs[2].get_repodir()
+                self.durl2 = self.dcs[2].get_depot_url()
+                self.published_targ = self.pkgsend_bulk(self.dpath2,
+                    self.targ_pkgs)
+
+                self.dpath3 = self.dcs[3].get_repodir()
+                self.durl3 = self.dcs[3].get_depot_url()
+                self.published_exp = self.pkgsend_bulk(self.dpath3,
+                    self.exp_pkgs)
+
+                # keep a tmp repo to copy the target into for each new test 
+                self.dpath_tmp = self.dcs[4].get_repodir()
+                
+        def test_0_options(self):
+                """Check for correct input handling."""
+                self.pkgsurf("-x", exit=2)
+                self.pkgsurf("-s pacific", exit=2)
+                self.pkgsurf("-s pacific -r atlantic arctic antarctic", exit=2)
+                # invalid patterns for -c
+                self.pkgsurf("-n -s %s -r %s -c [email protected]" % (self.dpath2,
+                    self.dpath1), exit=1)
+                self.pkgsurf("-n -s %s -r %s -c tig" % (self.dpath2,
+                    self.dpath1), exit=1)
+
+                # Check that -n doesn't modify repo.
+                tmpdir = tempfile.mkdtemp(dir=self.test_root)
+                path = os.path.join(tmpdir, "repo")
+                shutil.copytree(self.dpath2, path)
+
+                self.pkgsurf("-s %s -r %s -n" % (self.dpath2, self.dpath1))
+
+                ret = subprocess.call(["/usr/bin/gdiff", "-Naur", path,
+                    self.dpath2])
+                self.assertTrue(ret==0)
+
+        def test_1_basics(self):
+                """Test basic resurfacing operation."""
+
+                # Copy target repo to tmp repo
+                self.copy_repository(self.dpath2, self.dpath_tmp,
+                    { "selachii": "selachii" })
+                # The new repository won't have a catalog, so rebuild it.
+                self.dcs[4].get_repo(auto_create=True).rebuild()
+                #self.assertTrue(False)
+
+                # Check that empty repos get handled correctly
+                tempdir = tempfile.mkdtemp(dir=self.test_root)
+                # No repo at all
+                self.pkgsurf("-s %s -r %s" % (tempdir, self.dpath1), exit=1)
+                self.pkgsurf("-s %s -r %s" % (self.dpath1, tempdir), exit=1)
+
+                # Repo empty 
+                self.pkgrepo("create -s %s" % tempdir)
+                self.pkgsurf("-s %s -r %s" % (tempdir, self.dpath1), exit=1)
+                self.pkgsurf("-s %s -r %s" % (self.dpath1, tempdir), exit=1)
+
+                # No packages
+                self.pkgrepo("add-publisher -s %s selachii" % tempdir)
+                self.pkgsurf("-s %s -r %s" % (tempdir, self.dpath1))
+                self.assertTrue("No packages to reversion." in self.output)
+                self.pkgsurf("-s %s -r %s" % (self.dpath1, tempdir))
+                self.assertTrue("No packages to reversion." in self.output)
+                shutil.rmtree(tempdir)             
+
+                # Now check if it actually works.
+                self.pkgsurf("-s %s -r %s" % (self.dpath_tmp, self.dpath1))
+
+                ref_repo = self.get_repo(self.dpath1)
+                targ_repo = self.get_repo(self.dpath_tmp)
+                exp_repo = self.get_repo(self.dpath3)
+                for s in self.published_exp:
+                        f = fmri.PkgFmri(s, None)
+                        targ = targ_repo.manifest(f)
+
+                        # Load target manifest
+                        targm = manifest.Manifest()
+                        targm.set_content(pathname=targ)
+
+                        # Load expected manifest
+                        exp = exp_repo.manifest(f)
+                        expm = manifest.Manifest()
+                        expm.set_content(pathname=exp)
+
+                        ta, ra, ca = manifest.Manifest.comm([targm, expm])
+                        self.debug("%s: %d %d" %(str(s), len(ta), len(ra)))
+
+                        self.assertEqual(0, len(ta), "%s had unexpected actions:"
+                            " \n%s" % (s, "\n".join([str(x) for x in ta])))
+                        self.assertEqual(0, len(ra), "%s had missing actions: "
+                            "\n%s" % (s, "\n".join([str(x) for x in ra])))
+
+                # Check that pkgsurf informed the user that there is a newer
+                # version of a pkg in the ref repo.
+                self.assertTrue("Packages with successors" in self.output)
+
+                # Check that ignore option works.
+                # Just run again and see if goblin pkg now gets reversioned.
+                self.pkgsurf("-s %s -r %s -i info.home" % (self.dpath_tmp,
+                    self.dpath1))
+                
+                # Find goblin package
+                for s in self.published_ref:
+                        if "goblin" in s:
+                                break
+                f = fmri.PkgFmri(s, None)
+                targ = targ_repo.manifest(f)
+                ref = ref_repo.manifest(f)
+                self.assertEqual(misc.get_data_digest(targ),
+                    misc.get_data_digest(ref))
+
+                # Check that running the tool again doesn't find any pkgs
+                # to reversion. Use http for accessing reference repo this time.
+                self.pkgsurf("-s %s -r %s" % (self.dpath_tmp, self.durl1))
+                self.assertTrue("No packages to reversion." in self.output)
+
+        def test_2_publishers(self):
+                """Tests for correct publisher handling."""
+
+                # Copy target repo to tmp repo
+                self.copy_repository(self.dpath2, self.dpath_tmp,
+                    { "selachii": "selachii" })
+                # The new repository won't have a catalog, so rebuild it.
+                self.dcs[4].get_repo(auto_create=True).rebuild()
+
+                # Add a package from a different publisher to target
+                self.pkgsend_bulk(self.dpath_tmp, [self.humpback_targ])
+
+                # Test that unknown publisher in ref repo gets skipped without
+                # issue.
+                self.pkgsurf("-s %s -r %s -n" % (self.dpath_tmp,
+                    self.dpath1))
+                # Test that we also print a skipping notice
+                self.assertTrue("Skipping" in self.output)
+
+                # Test that we fail if we specify a publisher which is not in
+                # reference repo.
+                self.pkgsurf("-s %s -r %s -p cetacea -n" % (self.dpath_tmp,
+                    self.dpath1), exit=1)
+
+                # Now add packages from the 2nd pub to the ref repo
+                self.pkgsend_bulk(self.durl1, [self.humpback_ref])
+
+                # Test that only specified publisher is processed
+                self.pkgsurf("-s %s -r %s -p cetacea -n" % (self.dpath_tmp,
+                    self.dpath1))
+                self.assertFalse("selachii" in self.output)
+                self.pkgsurf("-s %s -r %s -p selachii -n" % (self.dpath_tmp,
+                    self.dpath1))
+                self.assertFalse("cetacea" in self.output)
+
+                # Now do an actual resurfacing of just one publisher
+                self.pkgsurf("-s %s -r %s -p selachii" % (self.dpath_tmp,
+                    self.dpath1))
+                # Check if we see anything about the unspecified publisher
+                # in the output.
+                self.assertFalse("cetacea" in self.output)
+                # Check if we didn't reversion packages of the unspecified
+                # publisher.
+                self.pkgrepo("-s %s list humpback" % (self.dpath_tmp))
+                self.assertTrue("2.0" in self.output)
+
+        def test_3_override_pkgs(self):
+                """Test for correct handling of user specified packages which
+                should not get reversioned."""
+
+                # Copy target repo to tmp repo
+                self.copy_repository(self.dpath2, self.dpath_tmp,
+                    { "selachii": "selachii" })
+                # The new repository won't have a catalog, so rebuild it.
+                self.dcs[4].get_repo(auto_create=True).rebuild()
+
+                # Check multiple patterns with globbing
+                self.pkgsurf("-s %s -r %s -c *iger" % (self.dpath_tmp,
+                    self.dpath1))
+                self.pkgrepo("-s %s list tiger" % (self.dpath_tmp))
+                self.assertTrue("2.0" in self.output)
+                self.pkgrepo("-s %s list sandtiger" % (self.dpath_tmp))
+                self.assertTrue("2.0" in self.output)
+
+                # Check specific name.
+                self.pkgsurf("-s %s -r %s -c tiger" % (self.dpath_tmp,
+                    self.dpath1))
+                self.pkgrepo("-s %s list tiger" % (self.dpath_tmp))
+                self.assertTrue("2.0" in self.output)
+
+
+if __name__ == "__main__":
+                unittest.main()
--- a/src/tests/cli/t_sysrepo.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/cli/t_sysrepo.py	Wed Aug 14 11:12:35 2013 +0530
@@ -22,7 +22,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -51,34 +51,19 @@
 
 SYSREPO_USER = "pkg5srv"
 
-class TestBasicSysrepoCli(pkg5unittest.CliTestCase):
+class TestBasicSysrepoCli(pkg5unittest.ApacheDepotTestCase):
         """Some basic tests checking that we can deal with all of our arguments
         and that we handle invalid input correctly."""
 
         def setUp(self):
                 self.sc = None
-                pkg5unittest.CliTestCase.setUp(self)
+                pkg5unittest.ApacheDepotTestCase.setUp(self, ["test"])
                 self.image_create()
                 self.default_sc_runtime = os.path.join(self.test_root,
                     "sysrepo_runtime")
                 self.default_sc_conf = os.path.join(self.default_sc_runtime,
                     "sysrepo_httpd.conf")
 
-        def tearDown(self):
-                try:
-                        pkg5unittest.CliTestCase.tearDown(self)
-                finally:
-                        if self.sc:
-                                self.debug("stopping sysrepo")
-                                try:
-                                        self.sc.stop()
-                                except Exception, e:
-                                        try:
-                                                self.debug("killing sysrepo")
-                                                self.sc.kill()
-                                        except Exception, e:
-                                                pass
-
         def _start_sysrepo(self, runtime_dir=None):
                 if not runtime_dir:
                         runtime_dir = self.default_sc_runtime
@@ -86,6 +71,7 @@
                 self.next_free_port += 1
                 self.sc = pkg5unittest.SysrepoController(self.default_sc_conf,
                     self.sysrepo_port, runtime_dir, testcase=self)
+                self.register_apache_controller("sysrepo", self.sc)
                 self.sc.start()
 
         def test_0_sysrepo(self):
@@ -145,7 +131,7 @@
                         port = self.next_free_port
                         ret, output, err = self.sysrepo("-l %s -p %s" %
                             (invalid_log, port), out=True, stderr=True, exit=0)
-                        self.assertRaises(pkg5unittest.SysrepoStateException,
+                        self.assertRaises(pkg5unittest.ApacheStateException,
                             self._start_sysrepo)
                         self.sc.stop()
 
@@ -209,7 +195,7 @@
                              "did not contain https_proxy: %s" % err)
 
 
-class TestDetailedSysrepoCli(pkg5unittest.ManyDepotTestCase):
+class TestDetailedSysrepoCli(pkg5unittest.ApacheDepotTestCase):
 
         persistent_setup = True
 
@@ -226,13 +212,12 @@
         misc_files = ["tmp/sample_file"]
 
         def setUp(self):
-                self.sc = None
                 # see test_7_response_overlaps
                 self.overlap_pubs = ["versions", "versionsX", "syspub",
                     "Xsyspub"]
                 pubs = ["test1", "test2"]
                 pubs.extend(self.overlap_pubs)
-                pkg5unittest.ManyDepotTestCase.setUp(self, pubs,
+                pkg5unittest.ApacheDepotTestCase.setUp(self, pubs,
                     start_depots=True)
 
                 # Most tests use a single system-repository instance, "sc",
@@ -262,32 +247,6 @@
                         durl = self.dcs[dc_num].get_depot_url()
                         self.pkgsend_bulk(durl, self.sample_pkg)
 
-        def killalldepots(self):
-                try:
-                        pkg5unittest.ManyDepotTestCase.killalldepots(self)
-                finally:
-                        if self.sc:
-                                self.debug("stopping sysrepo")
-                                try:
-                                        self.sc.stop()
-                                except Exception, e:
-                                        try:
-                                                self.debug("killing sysrepo")
-                                                self.sc.kill()
-                                        except Exception, e:
-                                                pass
-                        if self.alt_sc:
-                                self.debug("stopping alt sysrepo")
-                                try:
-                                        self.alt_sc.stop()
-                                except Exception, e:
-                                        try:
-                                                self.debug(
-                                                    "killing alt sysrepo")
-                                                self.alt_ac.stop()
-                                        except Exception, e:
-                                                pass
-
         def _start_sysrepo(self, runtime_dir=None, alt=False):
                 """Starts a system repository instance, either using the default
                 or alternative configurations."""
@@ -301,11 +260,15 @@
                         runtime_dir = self.alt_sc_runtime
                         self.alt_sc = pkg5unittest.SysrepoController(conf,
                             self.sysrepo_port, runtime_dir, testcase=self)
+                        self.register_apache_controller("alt_sysrepo",
+                            self.alt_sc)
                         self.alt_sc.start()
                 else:
                         self.sc = pkg5unittest.SysrepoController(
                             self.default_sc_conf,
                             self.sysrepo_port, runtime_dir, testcase=self)
+                        self.register_apache_controller("sysrepo",
+                            self.sc)
                         self.sc.start()
 
         def test_1_substring_proxy(self):
@@ -1030,7 +993,7 @@
                 # lives outside our normal search path
                 mod_name = "sysrepo_p5p"
                 src_name = "%s.py" % mod_name
-                sysrepo_p5p_file = file(os.path.join(self.template_dir,
+                sysrepo_p5p_file = file(os.path.join(self.sysrepo_template_dir,
                     src_name))
                 self.sysrepo_p5p = imp.load_module(mod_name, sysrepo_p5p_file,
                     src_name, ("py", "r", imp.PY_SOURCE))
--- a/src/tests/pkg5unittest.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/pkg5unittest.py	Wed Aug 14 11:12:35 2013 +0530
@@ -24,6 +24,7 @@
 # Define the basic classes that all test cases are inherited from.
 # The currently defined test case classes are:
 #
+# ApacheDepotTestCase
 # CliTestCase
 # ManyDepotTestCase
 # Pkg5TestCase
@@ -51,6 +52,7 @@
 import sys
 import tempfile
 import time
+import traceback
 import unittest
 import urllib2
 import urlparse
@@ -130,7 +132,7 @@
 
 # Version test suite is known to work with.
 PKG_CLIENT_NAME = "pkg"
-CLIENT_API_VERSION = 73
+CLIENT_API_VERSION = 75
 
 ELIDABLE_ERRORS = [ TestSkippedException, depotcontroller.DepotStateException ]
 
@@ -554,7 +556,8 @@
                     g_proto_area,
                     "pkglint.exclude": ""}, self.test_root, section="pkglint")
 
-                self.template_dir = "%s/etc/pkg/sysrepo" % g_proto_area
+                self.sysrepo_template_dir = "%s/etc/pkg/sysrepo" % g_proto_area
+                self.depot_template_dir = "%s/etc/pkg/depot" % g_proto_area
                 self.make_misc_files(self.smf_cmds, prefix="smf_cmds",
                     mode=0755)
                 DebugValues["smf_cmds_dir"] = \
@@ -802,7 +805,9 @@
                         assert(not prefix.startswith(os.pathsep))
                         prefix = os.path.join(self.test_root, prefix)
 
-                for f, content in files.items():
+                # Ensure output paths are returned in consistent order.
+                for f in sorted(files):
+                        content = files[f]
                         assert not f.startswith("/"), \
                             ("%s: misc file paths must be relative!" % f)
                         path = os.path.join(prefix, f)
@@ -2312,7 +2317,7 @@
                 return api_inst
 
         def pkg_image_create(self, repourl=None, prefix=None,
-            additional_args="", exit=0):
+            additional_args="", exit=0, env_arg=None):
                 """Executes pkg(1) client to create a full (as opposed to user)
                 image; returns exit code of client or raises an exception if
                 exit code doesn't match 'exit' or equals 99."""
@@ -2322,29 +2327,36 @@
 
                 self.image_destroy()
                 os.mkdir(self.img_path())
-                self.debug("pkg_image_create %s" % self.img_path())
                 cmdline = "%s image-create -F " % self.pkg_cmdpath
                 if repourl:
                         cmdline = "%s -p %s=%s " % (cmdline, prefix, repourl)
                 cmdline += additional_args
                 cmdline = "%s %s" % (cmdline, self.img_path())
-                self.debugcmd(cmdline)
-
-                p = subprocess.Popen(cmdline, shell=True,
-                    stdout=subprocess.PIPE,
-                    stderr=subprocess.STDOUT)
-                output = p.stdout.read()
-                retcode = p.wait()
-                self.debugresult(retcode, 0, output)
-
-                if retcode == 99:
-                        raise TracebackException(cmdline, output)
-                if retcode != exit:
-                        raise UnexpectedExitCodeException(cmdline, 0,
-                            retcode, output)
+
+                retcode = self.cmdline_run(cmdline, exit=exit, env_arg=env_arg)
+
                 self.__setup_signing_files()
                 return retcode
 
+        def image_clone(self, dst):
+
+                # the currently selected image is the source
+                src = self.img_index()
+                src_path = self.img_path()
+
+                # create an empty destination image
+                self.set_image(dst)
+                self.image_destroy()
+                os.mkdir(self.img_path())
+                dst_path = self.img_path()
+
+                # reactivate the source image
+                self.set_image(src)
+
+                # populate the destination image
+                cmdline = "cd %s; find . | cpio -pdm %s" % (src_path, dst_path)
+                retcode = self.cmdline_run(cmdline, coverage=False)
+
         def image_destroy(self):
                 if os.path.exists(self.img_path()):
                         self.debug("image_destroy %s" % self.img_path())
@@ -2358,11 +2370,12 @@
 
         def pkg(self, command, exit=0, comment="", prefix="", su_wrap=None,
             out=False, stderr=False, cmd_path=None, use_img_root=True,
-            debug_smf=True, env_arg=None):
+            debug_smf=True, env_arg=None, coverage=True):
                 if debug_smf and "smf_cmds_dir" not in command:
                         command = "--debug smf_cmds_dir=%s %s" % \
                             (DebugValues["smf_cmds_dir"], command)
                 command = "-D plandesc_validate=1 %s" % command
+                command = "-D manifest_validate=Always %s" % command
                 if use_img_root and "-R" not in command and \
                     "image-create" not in command and "version" not in command:
                         command = "-R %s %s" % (self.get_img_path(), command)
@@ -2371,28 +2384,38 @@
                 cmdline = "%s %s" % (cmd_path, command)
                 return self.cmdline_run(cmdline, exit=exit, comment=comment,
                     prefix=prefix, su_wrap=su_wrap, out=out, stderr=stderr,
-                    env_arg=env_arg)
-
-        def pkgdepend_resolve(self, args, exit=0, comment="", su_wrap=False):
+                    env_arg=env_arg, coverage=coverage)
+
+        def pkgdepend_resolve(self, args, exit=0, comment="", su_wrap=False,
+            env_arg=None):
                 ops = ""
                 if "-R" not in args:
                         ops = "-R %s" % self.get_img_path()
                 cmdline = "%s/usr/bin/pkgdepend %s resolve %s" % (
                     g_proto_area, ops, args)
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    su_wrap=su_wrap)
-
-        def pkgdepend_generate(self, args, exit=0, comment="", su_wrap=False):
+                    su_wrap=su_wrap, env_arg=env_arg)
+
+        def pkgdepend_generate(self, args, exit=0, comment="", su_wrap=False,
+            env_arg=None):
                 cmdline = "%s/usr/bin/pkgdepend generate %s" % (g_proto_area,
                     args)
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    su_wrap=su_wrap)
-
-        def pkgfmt(self, args, exit=0, su_wrap=False):
+                    su_wrap=su_wrap, env_arg=env_arg)
+
+        def pkgdiff(self, command, comment="", exit=0, su_wrap=False,
+            env_arg=None, stderr=False, out=False):
+                cmdline = "%s/usr/bin/pkgdiff %s" % (g_proto_area, command)
+                return self.cmdline_run(cmdline, comment=comment, exit=exit,
+                    su_wrap=su_wrap, env_arg=env_arg, out=out, stderr=stderr)
+
+        def pkgfmt(self, args, exit=0, su_wrap=False, env_arg=None):
                 cmd="%s/usr/bin/pkgfmt %s" % (g_proto_area, args)
-                self.cmdline_run(cmd, exit=exit, su_wrap=su_wrap)
-
-        def pkglint(self, args, exit=0, comment="", testrc=True):
+                self.cmdline_run(cmd, exit=exit, su_wrap=su_wrap,
+                    env_arg=env_arg)
+
+        def pkglint(self, args, exit=0, comment="", testrc=True,
+            env_arg=None):
                 if testrc:
                         rcpath = "%s/pkglintrc" % self.test_root
                         cmdline = "%s/usr/bin/pkglint -f %s %s" % \
@@ -2400,10 +2423,10 @@
                 else:
                         cmdline = "%s/usr/bin/pkglint %s" % (g_proto_area, args)
                 return self.cmdline_run(cmdline, exit=exit, out=True,
-                    comment=comment, stderr=True)
+                    comment=comment, stderr=True, env_arg=env_arg)
 
         def pkgrecv(self, server_url=None, command=None, exit=0, out=False,
-            comment=""):
+            comment="", env_arg=None, su_wrap=False):
                 args = []
                 if server_url:
                         args.append("-s %s" % server_url)
@@ -2413,21 +2436,30 @@
 
                 cmdline = "%s/usr/bin/pkgrecv %s" % (g_proto_area,
                     " ".join(args))
+
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    out=out)
-
-        def pkgmerge(self, args, comment="", exit=0, su_wrap=False):
+                    out=out, su_wrap=su_wrap, env_arg=env_arg)
+
+        def pkgmerge(self, args, comment="", exit=0, su_wrap=False,
+            env_arg=None):
                 cmdline = "%s/usr/bin/pkgmerge %s" % (g_proto_area, args)
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    su_wrap=su_wrap)
+                    su_wrap=su_wrap, env_arg=env_arg)
 
         def pkgrepo(self, command, comment="", exit=0, su_wrap=False,
-            stderr=False):
+            env_arg=None, stderr=False, out=False):
                 cmdline = "%s/usr/bin/pkgrepo %s" % (g_proto_area, command)
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    su_wrap=su_wrap, stderr=stderr)
-
-        def pkgsign(self, depot_url, command, exit=0, comment=""):
+                    su_wrap=su_wrap, env_arg=env_arg, out=out, stderr=stderr)
+
+        def pkgsurf(self, command, comment="", exit=0, su_wrap=False,
+            env_arg=None, stderr=False, out=False):
+                cmdline = "%s/usr/bin/pkgsurf %s" % (g_proto_area, command)
+                return self.cmdline_run(cmdline, comment=comment, exit=exit,
+                    su_wrap=su_wrap, env_arg=env_arg, out=out, stderr=stderr)
+
+        def pkgsign(self, depot_url, command, exit=0, comment="",
+            env_arg=None):
                 args = []
                 if depot_url:
                         args.append("-s %s" % depot_url)
@@ -2437,9 +2469,10 @@
 
                 cmdline = "%s/usr/bin/pkgsign %s" % (g_proto_area,
                     " ".join(args))
-                return self.cmdline_run(cmdline, comment=comment, exit=exit)
-
-        def pkgsign_simple(self, depot_url, pkg_name, exit=0):
+                return self.cmdline_run(cmdline, comment=comment, exit=exit,
+                    env_arg=env_arg)
+
+        def pkgsign_simple(self, depot_url, pkg_name, exit=0, env_arg=None):
                 chain_cert_path = os.path.join(self.chain_certs_dir,
                     "ch1_ta3_cert.pem")
                 sign_args = "-k %(key)s -c %(cert)s -i %(ch1)s %(name)s" % {
@@ -2448,10 +2481,11 @@
                     "cert": os.path.join(self.cs_dir, "cs1_ch1_ta3_cert.pem"),
                     "ch1": chain_cert_path,
                 }
-                return self.pkgsign(depot_url, sign_args, exit=exit)
+                return self.pkgsign(depot_url, sign_args, exit=exit,
+                    env_arg=env_arg)
 
         def pkgsend(self, depot_url="", command="", exit=0, comment="",
-            allow_timestamp=False, su_wrap=False):
+            allow_timestamp=False, env_arg=None, su_wrap=False):
                 args = []
                 if allow_timestamp:
                         args.append("-D allow-timestamp")
@@ -2467,7 +2501,7 @@
 
                 retcode, out = self.cmdline_run(cmdline, comment=comment,
                     exit=exit, out=True, prefix=prefix, raise_error=False,
-                    su_wrap=su_wrap)
+                    env_arg=env_arg, su_wrap=su_wrap)
                 errout = self.errout
 
                 cmdop = command.split(' ')[0]
@@ -2604,7 +2638,7 @@
                 self.cmdline_run(cmd, exit=exit)
 
         def sysrepo(self, args, exit=0, out=False, stderr=False, comment="",
-            fill_missing_args=True):
+            env_arg=None, fill_missing_args=True):
                 ops = ""
                 if "-R" not in args:
                         args += " -R %s" % self.get_img_path()
@@ -2620,13 +2654,59 @@
                         args += " -r %s" % os.path.join(self.test_root,
                             "sysrepo_runtime")
                 if "-t" not in args:
-                        args += " -t %s" % self.template_dir
-
-                cmdline = "%s/usr/lib/pkg.sysrepo %s" % (
-                    g_proto_area, args)
-                e = {"PKG5_TEST_ENV": "1"}
+                        args += " -t %s" % self.sysrepo_template_dir
+
+                cmdline = "%s/usr/lib/pkg.sysrepo %s" % (g_proto_area, args)
+                if env_arg is None:
+                        env_arg = {}
+                env_arg["PKG5_TEST_ENV"] = "1"
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    out=out, stderr=stderr, env_arg=e)
+                    out=out, stderr=stderr, env_arg=env_arg)
+
+        def snooze(self, sleeptime=10800, show_stack=True):
+                """A convenient method to cause test execution to pause for
+                up to 'sleeptime' seconds, which can be helpful during testcase
+                development.  sleeptime defaults to 3 hours."""
+                self.debug("YAWN ... going to sleep now\n")
+                if show_stack:
+                        self.debug("\n\n\n")
+                        self.debug("".join(traceback.format_stack()))
+                time.sleep(sleeptime)
+
+        def depotconfig(self, args, exit=0, out=False, stderr=False, comment="",
+            env_arg=None, fill_missing_args=True, debug_smf=True):
+                """Run pkg.depot-config, with command line arguments in args.
+                If fill_missing_args is set, we use default settings for several
+                arguments to point to template, logs, cache and proto areas
+                within our test root."""
+
+                if "-S" not in args and "-d" not in args and fill_missing_args:
+                        args += " -S "
+                if "-c" not in args and fill_missing_args:
+                        args += " -c %s" % os.path.join(self.test_root,
+                            "depot_cache")
+                if "-l" not in args:
+                        args += " -l %s" % os.path.join(self.test_root,
+                            "depot_logs")
+                if "-p" not in args and "-F" not in args and fill_missing_args:
+                        args += " -p %s" % self.depot_port
+                if "-r" not in args:
+                        args += " -r %s" % os.path.join(self.test_root,
+                            "depot_runtime")
+                if "-T" not in args:
+                        args += " -T %s" % self.depot_template_dir
+
+                if debug_smf and "smf_cmds_dir" not in args:
+                        args += " --debug smf_cmds_dir=%s" % \
+                            DebugValues["smf_cmds_dir"]
+
+                cmdline = "%s/usr/lib/pkg.depot-config %s" % (g_proto_area,
+                    args)
+                if env_arg is None:
+                        env_arg = {}
+                env_arg["PKG5_TEST_PROTO"] = g_proto_area
+                return self.cmdline_run(cmdline, comment=comment, exit=exit,
+                    out=out, stderr=stderr, env_arg=env_arg)
 
         def copy_repository(self, src, dest, pub_map):
                 """Copies the packages from the src repository to a new
@@ -3218,6 +3298,514 @@
                 CliTestCase.run(self, result)
 
 
+class ApacheDepotTestCase(ManyDepotTestCase):
+        """A TestCase that uses one or more Apache instances in the course of
+        its work, along with potentially one or more DepotControllers.
+        """
+
+        def __init__(self, methodName="runTest"):
+                super(ManyDepotTestCase, self).__init__(methodName)
+                self.dcs = {}
+                self.acs = {}
+
+        def register_apache_controller(self, name, ac):
+                """Registers an ApacheController with this TestCase.
+                We include this method here to make it easier to kill any
+                instances of Apache that were left floating around at the end
+                of the test.
+
+                We enforce the use of this method in
+                <ApacheController>.start() by refusing to start instances until
+                they are registered, which makes the test suite as a whole more
+                resilient, when setting up and tearing down test classes."""
+
+                if name in self.acs:
+                        # registering an Apache controller that is already
+                        # registered causes us to kill the existing controller
+                        # first.
+                        try:
+                                self.acs[name].stop()
+                        except Exception, e:
+                                try:
+                                        self.acs[name].kill()
+                                except Exception, e:
+                                        pass
+                self.acs[name] = ac
+
+        def __get_ac(self):
+                """If we only use a single ApacheController, self.ac will
+                return that controller, otherwise we return None."""
+                if self.acs and len(self.acs) == 1:
+                        return self.acs[self.acs.keys()[0]]
+                else:
+                        return None
+
+        def killalldepots(self):
+                try:
+                        ManyDepotTestCase.killalldepots(self)
+                finally:
+                        for name, ac in self.acs.items():
+                                self.debug("stopping apache controller %s" %
+                                    name)
+                                try:
+                                        ac.stop()
+                                except Exception, e :
+                                        try:
+                                                self.debug("killing apache "
+                                                    "instance %s" % name)
+                                                ac.kill()
+                                        except Exception, e:
+                                                self.debug("Unable to kill "
+                                                    "apache instance %s. This "
+                                                    "could cause subsequent "
+                                                    "tests to fail." % name)
+
+        # ac is a readonly property which returns a registered ApacheController
+        # provided there is exactly one registered, for convenience of writing
+        # test cases.
+        ac = property(fget=__get_ac)
+
+class HTTPSTestClass(ApacheDepotTestCase):
+        # Tests in this suite use the read only data directory.
+        need_ro_data = True
+
+        def pkg(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "--debug ssl_ca_file=%s %s" % \
+                    (DebugValues["ssl_ca_file"], command)
+                return ApacheDepotTestCase.pkg(self, command,
+                    *args, **kwargs)
+
+        def pkgrecv(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "%s --debug ssl_ca_file=%s" % \
+                    (command, DebugValues["ssl_ca_file"])
+                return ApacheDepotTestCase.pkgrecv(self, command,
+                    *args, **kwargs)
+
+        def pkgsend(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "%s --debug ssl_ca_file=%s" % \
+                    (command, DebugValues["ssl_ca_file"])
+                return ApacheDepotTestCase.pkgsend(self, command,
+                    *args, **kwargs)
+
+        def pkgrepo(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "--debug ssl_ca_file=%s %s" % \
+                    (DebugValues["ssl_ca_file"], command)
+                return ApacheDepotTestCase.pkgrepo(self, command,
+                    *args, **kwargs)
+
+        def seed_ta_dir(self, certs, dest_dir=None):
+                if isinstance(certs, basestring):
+                        certs = [certs]
+                if not dest_dir:
+                        dest_dir = self.ta_dir
+                self.assert_(dest_dir)
+                self.assert_(self.raw_trust_anchor_dir)
+                for c in certs:
+                        name = "%s_cert.pem" % c
+                        portable.copyfile(
+                            os.path.join(self.raw_trust_anchor_dir, name),
+                            os.path.join(dest_dir, name))
+                        DebugValues["ssl_ca_file"] = os.path.join(dest_dir,
+                            name)
+
+        def get_cli_cert(self, publisher):
+                ta = self.pub_ta_map[publisher]
+                return "cs1_ta%d_cert.pem" % ta
+
+        def get_cli_key(self, publisher):
+                ta = self.pub_ta_map[publisher]
+                return "cs1_ta%d_key.pem" % ta
+
+        def setUp(self, publishers, start_depots=True):
+                # We only have 5 usable CA certs and there are not many usecases
+                # for setting up more than 5 different SSL-secured depots.
+                assert len(publishers) < 6
+
+                # Maintains a mapping of which TA is used for which publisher
+                self.pub_ta_map = {}
+
+                ApacheDepotTestCase.setUp(self, publishers,
+                    start_depots=True)
+                self.testdata_dir = os.path.join(self.test_root, "testdata")
+
+                # Set up the directories that apache needs.
+                self.apache_dir = os.path.join(self.test_root, "apache")
+                os.makedirs(self.apache_dir)
+                self.apache_log_dir = os.path.join(self.apache_dir,
+                    "apache_logs")
+                os.makedirs(self.apache_log_dir)
+                self.apache_content_dir = os.path.join(self.apache_dir,
+                    "apache_content")
+                self.pidfile = os.path.join(self.apache_dir, "httpd.pid")
+                self.common_config_dir = os.path.join(self.test_root,
+                    "apache-serve")
+
+                # Choose ports for apache to run on.
+                self.https_port = self.next_free_port
+                self.next_free_port += 1
+                self.proxy_port = self.next_free_port
+                self.next_free_port += 1
+                self.bad_proxy_port = self.next_free_port
+                self.next_free_port += 1
+
+                # Set up the paths to the certificates that will be needed.
+                self.path_to_certs = os.path.join(self.ro_data_root,
+                    "signing_certs", "produced")
+                self.keys_dir = os.path.join(self.path_to_certs, "keys")
+                self.cs_dir = os.path.join(self.path_to_certs,
+                    "code_signing_certs")
+                self.chain_certs_dir = os.path.join(self.path_to_certs,
+                    "chain_certs")
+                self.pub_cas_dir = os.path.join(self.path_to_certs,
+                    "publisher_cas")
+                self.inter_certs_dir = os.path.join(self.path_to_certs,
+                    "inter_certs")
+                self.raw_trust_anchor_dir = os.path.join(self.path_to_certs,
+                    "trust_anchors")
+                self.crl_dir = os.path.join(self.path_to_certs, "crl")
+
+                location_tags = ""
+                # Usable CA certs are ta6 to ta11 with the exception of ta7.
+                # We already checked that not more than 5 publishers have been
+                # requested.
+                count = 6
+                for dc in self.dcs:
+                        # Create a <Location> tag for each publisher. The server
+                        # path is set to the publisher name.
+                        if count == 7:
+                                # TA7 needs password to unlock cert, don't use
+                                count += 1
+                        dc_pub = self.dcs[dc].get_property("publisher",
+                            "prefix")
+                        self.pub_ta_map[dc_pub] = count
+                        loc_dict = {
+                            "server-path":dc_pub,
+                            "server-ca-taname":"ta%d" % count,
+                            "ssl-special":"%{SSL_CLIENT_I_DN_OU}",
+                            "proxied-server":self.dcs[dc].get_depot_url(),
+                        }
+
+                        location_tags += loc_tag % (loc_dict)
+                        count += 1
+
+                conf_dict = {
+                    "common_log_format": "%h %l %u %t \\\"%r\\\" %>s %b",
+                    "https_port": self.https_port,
+                    "proxy_port": self.proxy_port,
+                    "bad_proxy_port": self.bad_proxy_port,
+                    "log_locs": self.apache_log_dir,
+                    "pidfile": self.pidfile,
+                    "port": self.https_port,
+                    "serve_root": self.apache_content_dir,
+                    "server-ssl-cert":os.path.join(self.cs_dir,
+                        "cs1_ta7_cert.pem"),
+                    "server-ssl-key":os.path.join(self.keys_dir,
+                        "cs1_ta7_key.pem"),
+                    "server-ca-cert":os.path.join(self.path_to_certs, "combined_cas.pem"),
+                    "location-tags":location_tags,
+                }
+
+                self.https_conf_path = os.path.join(self.test_root,
+                    "https.conf")
+                with open(self.https_conf_path, "wb") as fh:
+                        fh.write(self.https_conf % conf_dict)
+                
+                ac = ApacheController(self.https_conf_path,
+                    self.https_port, self.common_config_dir, https=True,
+                    testcase=self)
+                self.register_apache_controller("default", ac)
+
+        https_conf = """\
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "/var/apache2/2.2/logs/foo_log"
+# with ServerRoot set to "/usr/apache2/2.2" will be interpreted by the
+# server as "/usr/apache2/2.2//var/apache2/2.2/logs/foo_log".
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path.  If you point
+# ServerRoot at a non-local disk, be sure to point the LockFile directive
+# at a local disk.  If you wish to share the same ServerRoot for multiple
+# httpd daemons, you will need to change at least LockFile and PidFile.
+#
+ServerRoot "/usr/apache2/2.2"
+
+PidFile "%(pidfile)s"
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to 
+# prevent Apache from glomming onto all bound IP addresses.
+#
+Listen 0.0.0.0:%(https_port)s
+
+# We also make ourselves a general-purpose proxy. This is not needed for the
+# SSL reverse-proxying to the pkg.depotd, but allows us to test that pkg(1)
+# can communicate to HTTPS origins using a proxy.
+Listen 0.0.0.0:%(proxy_port)s
+Listen 0.0.0.0:%(bad_proxy_port)s
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines within the appropriate 
+# (32-bit or 64-bit module) /etc/apache2/2.2/conf.d/modules-*.load file so that
+# the directives contained in it are actually available _before_ they are used.
+#
+<IfDefine 64bit>
+Include /etc/apache2/2.2/conf.d/modules-64.load
+</IfDefine>
+<IfDefine !64bit>
+Include /etc/apache2/2.2/conf.d/modules-32.load
+</IfDefine>
+
+<IfModule !mpm_netware_module>
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.  
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User webservd
+Group webservd
+
+</IfModule>
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+ServerName 127.0.0.1
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+# First, we configure the "default" to be a very restrictive set of 
+# features.  
+#
+<Directory />
+    Options None
+    AllowOverride None
+    Order deny,allow
+    Deny from all
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+    DirectoryIndex index.html
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<FilesMatch "^\.ht">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</FilesMatch>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog "%(log_locs)s/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel debug
+
+
+
+<IfModule log_config_module>
+    #
+    # The following directives define some format nicknames for use with
+    # a CustomLog directive (see below).
+    #
+    LogFormat "%(common_log_format)s" common
+    LogFormat "PROXY %(common_log_format)s" proxylog
+
+    #
+    # The location and format of the access logfile (Common Logfile Format).
+    # If you do not define any access logfiles within a <VirtualHost>
+    # container, they will be logged here.  Contrariwise, if you *do*
+    # define per-<VirtualHost> access logfiles, transactions will be
+    # logged therein and *not* in this file.
+    #
+    CustomLog "%(log_locs)s/access_log" common
+</IfModule>
+
+#
+# DefaultType: the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+<IfModule mime_module>
+    #
+    # TypesConfig points to the file containing the list of mappings from
+    # filename extension to MIME-type.
+    #
+    TypesConfig /etc/apache2/2.2/mime.types
+
+    #
+    # AddType allows you to add to or override the MIME configuration
+    # file specified in TypesConfig for specific file types.
+    #
+    AddType application/x-compress .Z
+    AddType application/x-gzip .gz .tgz
+
+    # Add a new mime.type for .p5i file extension so that clicking on
+    # this file type on a web page launches PackageManager in a Webinstall mode.
+    AddType application/vnd.pkg5.info .p5i
+</IfModule>
+
+#
+# Note: The following must must be present to support
+#       starting without SSL on platforms with no /dev/random equivalent
+#       but a statically compiled-in mod_ssl.
+#
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+</IfModule>
+
+<VirtualHost 0.0.0.0:%(https_port)s>
+        AllowEncodedSlashes On
+        ProxyRequests Off
+        MaxKeepAliveRequests 10000
+
+        SSLEngine On
+
+        # Cert paths
+        SSLCertificateFile %(server-ssl-cert)s
+        SSLCertificateKeyFile %(server-ssl-key)s
+
+        # Combined product CA certs for client verification
+        SSLCACertificateFile %(server-ca-cert)s
+
+	SSLVerifyClient require
+
+        %(location-tags)s
+
+</VirtualHost>
+
+#
+# We configure this Apache instance as a general-purpose HTTP proxy, accepting
+# requests from localhost, and allowing CONNECTs to our HTTPS port
+#
+<VirtualHost 0.0.0.0:%(proxy_port)s>
+        <Proxy *>
+                Order Deny,Allow
+                Deny from all
+                Allow from 127.0.0.1
+        </Proxy>
+        AllowCONNECT %(https_port)s
+        ProxyRequests on
+        CustomLog "%(log_locs)s/proxy_access_log" proxylog
+</VirtualHost>
+
+<VirtualHost 0.0.0.0:%(bad_proxy_port)s>
+        <Proxy *>
+                Order Deny,Allow
+                Deny from all
+                Allow from 127.0.0.1
+        </Proxy>
+#  We purposely prevent this proxy from being able to connect to our SSL
+#  port, making sure that when we point pkg(1) to this bad proxy, operations
+#  will fail - the following line is commented out:
+#        AllowCONNECT %(https_port)s
+        ProxyRequests on
+        CustomLog "%(log_locs)s/badproxy_access_log" proxylog
+
+</VirtualHost>
+"""
+
+loc_tag = """
+        <Location /%(server-path)s>
+                SSLVerifyDepth 1
+
+	        # The client's certificate must pass verification, and must have
+	        # a CN which matches this repository.
+                SSLRequire ( %(ssl-special)s =~ m/%(server-ca-taname)s/ )
+
+                # set max to number of threads in depot
+                ProxyPass %(proxied-server)s nocanon max=500
+        </Location>
+"""
+
+
 class SingleDepotTestCase(ManyDepotTestCase):
 
         def setUp(self, debug_features=EmptyI, publisher="test",
@@ -3244,6 +3832,7 @@
         # for convenience of writing test cases.
         dc = property(fget=__get_dc)
 
+
 class SingleDepotTestCaseCorruptImage(SingleDepotTestCase):
         """ A class which allows manipulation of the image directory that
         SingleDepotTestCase creates. Specifically, it supports removing one
@@ -3298,30 +3887,17 @@
 
                 for s in subdirs:
                         if s == "var/pkg":
-                                cmdline = "pkg image-create -F -p %s=%s %s" % \
+                                cmdline = "image-create -F -p %s=%s %s" % \
                                     (prefix, repourl, self.img_path())
                         elif s == ".org.opensolaris,pkg":
-                                cmdline = "pkg image-create -U -p %s=%s %s" % \
+                                cmdline = "image-create -U -p %s=%s %s" % \
                                     (prefix, repourl, self.img_path())
                         else:
                                 raise RuntimeError("Got unknown subdir option:"
                                     "%s\n" % s)
 
-                        self.debugcmd(cmdline)
-
-                        # Run the command to actually create a good image
-                        p = subprocess.Popen(cmdline, shell=True,
-                                             stdout=subprocess.PIPE,
-                                             stderr=subprocess.STDOUT)
-                        output = p.stdout.read()
-                        retcode = p.wait()
-                        self.debugresult(retcode, 0, output)
-
-                        if retcode == 99:
-                                raise TracebackException(cmdline, output)
-                        if retcode != 0:
-                                raise UnexpectedExitCodeException(cmdline, 0,
-                                    retcode, output)
+                        cmdline = self.pkg_cmdpath + " " + cmdline
+                        self.cmdline_run(cmdline, exit=0)
 
                         tmpDir = os.path.join(self.img_path(), s)
 
@@ -3478,7 +4054,7 @@
         else:
                 raise RuntimeError("Function did not raise exception.")
 
-class SysrepoStateException(Exception):
+class ApacheStateException(Exception):
         pass
 
 class ApacheController(object):
@@ -3488,19 +4064,21 @@
                 The 'conf' parameter is a path to a httpd.conf file.  The 'port'
                 parameter is a port to run on.  The 'work_dir' is a temporary
                 directory to store runtime state.  The 'testcase' parameter is
-                the Pkg5TestCase to use when writing output.  The 'https'
+                the ApacheDepotTestCase to use when writing output.  The 'https'
                 parameter is a boolean indicating whether this instance expects
                 to be contacted via https or not.
                 """
 
-                self.apachectl = "/usr/apache2/2.2/bin/httpd"
+                self.apachectl = "/usr/apache2/2.2/bin/httpd.worker"
                 if not os.path.exists(work_dir):
                         os.makedirs(work_dir)
-                self.__conf_path = os.path.join(work_dir, "sysrepo.conf")
+                self.__conf_path = os.path.join(work_dir, "httpd.conf")
                 self.__port = port
                 self.__repo_hdl = None
                 self.__starttime = 0
-                self.__state = None
+                self.__state = "stopped"
+                if not testcase:
+                        raise RuntimeError("No testcase parameter specified")
                 self.__tc = testcase
                 prefix = "http"
                 if https:
@@ -3540,21 +4118,36 @@
                         self.__tc.debugresult(result, expected, msg)
 
         def start(self):
+                if self not in self.__tc.acs.values():
+                        # An attempt to start an ApacheController that has not
+                        # been registered can result in it not getting cleaned
+                        # up properly when the test completes, which can cause
+                        # other tests to fail. We don't allow that to happen.
+                        raise RuntimeError(
+                            "This ApacheController has not been registered with"
+                            " the ApacheDepotTestCase %s using "
+                            "set_apache_controller(name, ac)" % self.__tc)
+
                 if self._network_ping():
-                        raise SysrepoStateException("A depot (or some " +
+                        raise ApacheStateException("A depot (or some " +
                             "other network process) seems to be " +
                             "running on port %d already!" % self.__port)
                 cmdline = ["/usr/bin/setpgrp", self.apachectl, "-f",
                     self.__conf_path, "-k", "start", "-DFOREGROUND"]
                 try:
                         self.__starttime = time.time()
+                        # change the state so that we try to do work in
+                        # self.stop() in the face of a False result from
+                        # is_alive()
+                        self.__state = "starting"
                         self.debug(" ".join(cmdline))
                         self.__repo_hdl = subprocess.Popen(cmdline, shell=False,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
                         if self.__repo_hdl is None:
-                                raise SysrepoStateException("Could not start "
-                                    "sysrepo")
+                                self.__state = "stopped"
+                                raise ApacheStateException("Could not start "
+                                    "apache")
                         begintime = time.time()
 
                         check_interval = 0.20
@@ -3562,7 +4155,8 @@
                         while (time.time() - begintime) <= 40.0:
                                 rc = self.__repo_hdl.poll()
                                 if rc is not None:
-                                        raise SysrepoStateException("Sysrepo "
+                                        self.__state = "stopped"
+                                        raise ApacheStateException("Apache "
                                             "exited unexpectedly while "
                                             "starting (exit code %d)" % rc)
 
@@ -3573,7 +4167,7 @@
 
                         if contact == False:
                                 self.stop()
-                                raise SysrepoStateException("Sysrepo did not "
+                                raise ApacheStateException("Apache did not "
                                     "respond to repeated attempts to make "
                                     "contact")
                         self.__state = "started"
@@ -3679,8 +4273,8 @@
 
         def __init__(self, conf, port, work_dir, testcase=None, https=False):
                 ApacheController.__init__(self, conf, port, work_dir,
-                    testcase=None, https=False)
-                self.apachectl = "/usr/apache2/2.2/bin/64/httpd"
+                    testcase=testcase, https=False)
+                self.apachectl = "/usr/apache2/2.2/bin/64/httpd.worker"
 
         def _network_ping(self):
                 try:
@@ -3692,3 +4286,23 @@
                 except urllib2.URLError:
                         return False
                 return True
+
+
+class HttpDepotController(ApacheController):
+
+        def __init__(self, conf, port, work_dir, testcase=None, https=False):
+                ApacheController.__init__(self, conf, port, work_dir,
+                    testcase=testcase, https=False)
+                self.apachectl = "/usr/apache2/2.2/bin/64/httpd.worker"
+
+        def _network_ping(self):
+                try:
+                        urllib2.urlopen(self.url)
+                except urllib2.HTTPError, e:
+                        if e.code == httplib.FORBIDDEN:
+                                return True
+                        return False
+                except urllib2.URLError:
+                        return False
+                return True
+
--- a/src/tests/ro_data/signing_certs/generate_certs.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/ro_data/signing_certs/generate_certs.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -34,8 +34,8 @@
 cnf_file = "openssl.cnf"
 mk_file = "Makefile"
 
-subj_str = "/C=US/ST=California/L=Menlo Park/O=pkg5/CN=%s/emailAddress=%s"
-https_subj_str = "/C=US/ST=California/L=Menlo Park/O=pkg5/OU=%s/" \
+subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/CN=%s/emailAddress=%s"
+https_subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/OU=%s/" \
     "CN=localhost/emailAddress=%s"
 
 def convert_pem_to_text(tmp_pth, out_pth, kind="x509"):
@@ -91,7 +91,7 @@
 
 
 def make_cs_cert(new_loc, new_name, parent_loc, parent_name, ext="v3_req",
-    expired=False, future=False, https=False):
+    expired=False, future=False, https=False, passphrase=None):
         """Create a new code signing cert."""
 
         subj_str_to_use = subj_str
@@ -104,6 +104,15 @@
         p = subprocess.Popen(cmd)
         assert p.wait() == 0
 
+        if passphrase:
+                # Add a passphrase to the key just created using a new filename.
+                cmd = ["openssl", "rsa", "-des3",
+                    "-in", "./keys/%s_key.pem" % new_name,
+                    "-out", "./keys/%s_reqpass_key.pem" % new_name,
+                    "-passout", "pass:%s" % passphrase]
+                p = subprocess.Popen(cmd)
+                assert p.wait() == 0
+
         cmd = ["openssl", "ca", "-policy", "policy_anything",
             "-extensions", ext,
             "-out", "./%s/%s_cert.pem" % (new_loc, new_name),
@@ -128,6 +137,7 @@
         p = subprocess.Popen(cmd)
         assert p.wait() == 0
 
+
 def make_trust_anchor(name, https=False):
         """Make a new trust anchor."""
 
@@ -325,8 +335,9 @@
         make_cs_cert("code_signing_certs", "cs1_ta6", "trust_anchors", "ta6",
             https=True)
         make_trust_anchor("ta7", https=True)
+        # A passphrase is added to this one to test depot HTTPS functionality.
         make_cs_cert("code_signing_certs", "cs1_ta7", "trust_anchors", "ta7",
-            https=True)
+            https=True, passphrase="123")
         make_trust_anchor("ta8", https=True)
         make_cs_cert("code_signing_certs", "cs1_ta8", "trust_anchors", "ta8",
             https=True)
@@ -340,5 +351,17 @@
         make_cs_cert("code_signing_certs", "cs1_ta11", "trust_anchors", "ta11",
             https=True)
 
+        # Create a combined CA file to test different client certs with Apache
+        fhw = open("combined_cas.pem", "w")
+        for x in range(6,12):
+                if x == 7:
+                        # ta requires a password to unlock cert, don't use 
+                        continue
+                fn = "ta%d/ta%d_cert.pem" % (x,x)
+                fhr = open(fn, "r")
+                fhw.write(fhr.read())
+                fhr.close()
+        fhw.close()
+
         os.remove(cnf_file)
         os.chdir("../")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/ro_data/signing_certs/produced/combined_cas.pem	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,322 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            93:ae:7e:2d:c9:61:8f:4b
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta6, CN=localhost/emailAddress=ta6
+        Validity
+            Not Before: Apr 11 22:37:52 2011 GMT
+            Not After : Jan  5 22:37:52 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta6, CN=localhost/emailAddress=ta6
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:c5:41:a2:3d:00:af:e2:71:29:e6:18:c2:73:65:
+                    fc:4a:9d:e3:f7:1a:6e:7a:f5:09:81:87:cd:cf:a9:
+                    74:a9:e4:47:da:e2:fa:bd:0e:0a:ae:ba:06:e8:1b:
+                    66:e3:8a:5e:bb:87:90:5e:d1:38:7d:12:93:72:a0:
+                    4b:88:77:dd:ce:02:67:9f:c5:be:49:cb:b7:e8:0e:
+                    bd:f0:78:37:55:bb:c5:91:6e:c7:7b:9c:b3:94:a2:
+                    24:7d:09:25:74:52:22:6d:4a:34:f8:92:71:b1:e9:
+                    74:9b:8e:87:d4:2a:46:f8:fa:8f:86:5c:b5:6b:20:
+                    24:d1:37:ea:8a:87:07:e3:ad
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                0C:08:1A:2C:FA:77:26:CE:37:0F:A5:85:98:85:0F:4D:48:BA:83:B3
+            X509v3 Authority Key Identifier: 
+                keyid:0C:08:1A:2C:FA:77:26:CE:37:0F:A5:85:98:85:0F:4D:48:BA:83:B3
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta6/CN=localhost/emailAddress=ta6
+                serial:93:AE:7E:2D:C9:61:8F:4B
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        10:2c:ed:b9:a4:aa:bd:9e:4d:47:dd:02:64:52:a9:7a:73:a7:
+        f3:58:45:cf:da:5c:1e:80:30:d9:10:a7:e4:79:d2:eb:85:8b:
+        70:4c:39:df:b6:40:fb:7f:11:cd:a8:85:d6:5c:d1:2f:29:9f:
+        8d:fa:53:bc:20:f3:c8:97:9b:11:f4:7d:39:9a:2c:a6:6e:1e:
+        a4:0d:81:e0:65:59:89:f6:a9:66:65:38:05:44:e7:47:a2:9e:
+        a2:e3:82:07:2c:cb:8e:dc:47:a2:e9:cb:01:6a:54:c1:26:14:
+        03:e9:c3:ac:fe:98:0e:76:52:f3:5b:67:ea:26:0d:98:6d:e4:
+        23:ac
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJAJOufi3JYY9LMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTYxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE2MB4XDTExMDQxMTIyMzc1MloXDTE0MDEwNTIy
+Mzc1MlowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhNjESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTYwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAMVBoj0Ar+JxKeYYwnNl/Eqd4/cabnr1CYGHzc+pdKnk
+R9ri+r0OCq66BugbZuOKXruHkF7ROH0Sk3KgS4h33c4CZ5/FvknLt+gOvfB4N1W7
+xZFux3ucs5SiJH0JJXRSIm1KNPiScbHpdJuOh9QqRvj6j4ZctWsgJNE36oqHB+Ot
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFAwIGiz6dybONw+lhZiFD01IuoOzMIGvBgNV
+HSMEgacwgaSAFAwIGiz6dybONw+lhZiFD01IuoOzoYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhNjESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTaCCQCTrn4tyWGPSzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBABAs7bmkqr2eTUfdAmRSqXpzp/NYRc/aXB6AMNkQp+R50uuF
+i3BMOd+2QPt/Ec2ohdZc0S8pn436U7wg88iXmxH0fTmaLKZuHqQNgeBlWYn2qWZl
+OAVE50einqLjggcsy47cR6LpywFqVMEmFAPpw6z+mA52UvNbZ+omDZht5COs
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            b8:9a:b1:4d:fa:a9:68:23
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta8, CN=localhost/emailAddress=ta8
+        Validity
+            Not Before: Apr 11 22:37:54 2011 GMT
+            Not After : Jan  5 22:37:54 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta8, CN=localhost/emailAddress=ta8
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:da:5e:85:e0:17:14:35:c1:e8:f4:b6:97:15:d1:
+                    f5:c3:36:26:57:85:5c:0c:e8:8e:d7:2b:10:66:b2:
+                    61:92:a3:df:a4:4f:61:52:41:9c:3b:2f:0e:bc:bd:
+                    92:9b:e2:4c:ec:68:34:76:2c:86:54:e5:8b:9e:ac:
+                    2f:7e:4f:07:52:ec:7f:51:31:ed:9e:94:ed:7e:15:
+                    da:4f:fb:65:d0:07:85:c2:60:69:ce:ac:74:72:8a:
+                    45:31:e4:6c:3e:5e:05:bc:d3:2f:37:56:14:c2:2e:
+                    78:78:6b:93:14:e5:61:08:22:ef:4d:f9:bb:1b:1f:
+                    31:09:12:7a:ad:e5:cf:18:5b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                BB:CA:54:46:B9:0F:22:DB:69:82:15:BB:66:36:9D:50:1D:0B:1B:F5
+            X509v3 Authority Key Identifier: 
+                keyid:BB:CA:54:46:B9:0F:22:DB:69:82:15:BB:66:36:9D:50:1D:0B:1B:F5
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta8/CN=localhost/emailAddress=ta8
+                serial:B8:9A:B1:4D:FA:A9:68:23
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        7a:13:83:75:43:35:e1:4d:07:93:8d:1c:fd:4d:8f:5c:24:78:
+        f5:01:35:4c:a5:ad:5f:92:f3:23:21:0c:2d:dc:64:a5:7f:c2:
+        3c:c9:e3:b0:4e:d8:17:4e:76:4c:4d:71:fb:b9:3d:d9:51:b8:
+        fc:e0:91:a6:5c:18:c8:06:55:cc:a9:ba:9e:59:92:c4:5c:04:
+        11:e2:d9:99:1d:cb:bd:9d:6c:c2:0e:9e:f0:4c:20:69:6b:b1:
+        76:b6:d4:c0:e6:6c:4b:1e:18:cb:71:4a:9b:13:ca:db:c8:a4:
+        0e:35:c0:91:70:04:9c:32:bd:15:a2:36:72:97:d0:7b:d0:6c:
+        dc:03
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJALiasU36qWgjMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTgxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE4MB4XDTExMDQxMTIyMzc1NFoXDTE0MDEwNTIy
+Mzc1NFowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhODESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTgwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBANpeheAXFDXB6PS2lxXR9cM2JleFXAzojtcrEGayYZKj
+36RPYVJBnDsvDry9kpviTOxoNHYshlTli56sL35PB1Lsf1Ex7Z6U7X4V2k/7ZdAH
+hcJgac6sdHKKRTHkbD5eBbzTLzdWFMIueHhrkxTlYQgi7035uxsfMQkSeq3lzxhb
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFLvKVEa5DyLbaYIVu2Y2nVAdCxv1MIGvBgNV
+HSMEgacwgaSAFLvKVEa5DyLbaYIVu2Y2nVAdCxv1oYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhODESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTiCCQC4mrFN+qloIzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBAHoTg3VDNeFNB5ONHP1Nj1wkePUBNUylrV+S8yMhDC3cZKV/
+wjzJ47BO2BdOdkxNcfu5PdlRuPzgkaZcGMgGVcypup5ZksRcBBHi2Zkdy72dbMIO
+nvBMIGlrsXa21MDmbEseGMtxSpsTytvIpA41wJFwBJwyvRWiNnKX0HvQbNwD
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            a1:62:e1:e5:c0:a2:38:0d
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta9, CN=localhost/emailAddress=ta9
+        Validity
+            Not Before: Apr 11 22:37:54 2011 GMT
+            Not After : Jan  5 22:37:54 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta9, CN=localhost/emailAddress=ta9
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e8:ab:ef:91:ca:05:4a:18:a2:98:c4:d8:93:d0:
+                    ce:99:a9:5e:02:8d:5d:5c:e3:f3:84:49:6b:a7:6d:
+                    ef:38:77:2e:32:c2:9c:09:1d:f6:be:6c:c6:c4:b1:
+                    c8:c3:32:72:2b:84:87:f6:ba:bf:fc:cf:5c:05:c2:
+                    4f:62:23:7e:02:3f:ce:6c:c6:b6:95:86:84:d7:97:
+                    9f:1c:87:70:29:62:6a:29:7c:06:a3:b7:18:12:67:
+                    07:3a:89:aa:f0:99:fe:df:46:00:b1:2f:aa:30:1e:
+                    a2:1e:f8:2b:37:99:21:b8:85:53:42:98:4a:bd:c5:
+                    f9:b4:61:60:0a:73:bc:0e:d1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                A6:CF:35:00:96:15:AD:B4:24:DE:1D:5A:B9:56:A2:6E:B4:2D:46:C5
+            X509v3 Authority Key Identifier: 
+                keyid:A6:CF:35:00:96:15:AD:B4:24:DE:1D:5A:B9:56:A2:6E:B4:2D:46:C5
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta9/CN=localhost/emailAddress=ta9
+                serial:A1:62:E1:E5:C0:A2:38:0D
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        44:02:da:cf:c3:07:27:84:e4:06:22:ff:fc:7e:c9:47:7a:79:
+        e1:9f:6a:84:68:a8:fb:48:18:80:58:0f:b0:5e:ef:43:bf:3a:
+        69:23:b2:18:3e:78:3a:8e:ff:c5:d8:76:4c:99:d5:9f:be:8a:
+        fd:0e:79:b9:7e:62:c4:c2:4b:6f:78:01:e7:52:19:ff:08:86:
+        a7:b2:17:0c:11:03:ef:42:1f:b5:5b:40:0a:3a:9f:2a:4f:57:
+        31:3d:b1:dd:a8:51:e1:2f:b2:e4:5b:2e:1b:9f:a7:d6:b7:6b:
+        76:68:f9:2e:b1:38:6f:11:21:0e:81:a2:32:01:7b:bc:c3:1f:
+        82:4e
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJAKFi4eXAojgNMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTkxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE5MB4XDTExMDQxMTIyMzc1NFoXDTE0MDEwNTIy
+Mzc1NFowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhOTESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTkwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAOir75HKBUoYopjE2JPQzpmpXgKNXVzj84RJa6dt7zh3
+LjLCnAkd9r5sxsSxyMMyciuEh/a6v/zPXAXCT2IjfgI/zmzGtpWGhNeXnxyHcCli
+ail8BqO3GBJnBzqJqvCZ/t9GALEvqjAeoh74KzeZIbiFU0KYSr3F+bRhYApzvA7R
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFKbPNQCWFa20JN4dWrlWom60LUbFMIGvBgNV
+HSMEgacwgaSAFKbPNQCWFa20JN4dWrlWom60LUbFoYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhOTESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTmCCQChYuHlwKI4DTAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBAEQC2s/DByeE5AYi//x+yUd6eeGfaoRoqPtIGIBYD7Be70O/
+Omkjshg+eDqO/8XYdkyZ1Z++iv0Oebl+YsTCS294AedSGf8IhqeyFwwRA+9CH7Vb
+QAo6nypPVzE9sd2oUeEvsuRbLhufp9a3a3Zo+S6xOG8RIQ6BojIBe7zDH4JO
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            86:f1:45:12:31:c7:2b:2a
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta10, CN=localhost/emailAddress=ta10
+        Validity
+            Not Before: Apr 11 22:37:55 2011 GMT
+            Not After : Jan  5 22:37:55 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta10, CN=localhost/emailAddress=ta10
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:b6:50:43:73:64:12:40:26:54:0c:f9:67:e4:6a:
+                    ed:1f:18:e5:73:89:13:0f:c9:5f:6e:6e:c6:05:ad:
+                    2c:be:e4:6b:fd:c6:4f:ea:f3:6f:0d:f4:1a:34:7f:
+                    03:97:b0:a4:d1:6e:98:d2:36:fa:33:5d:51:37:de:
+                    8f:5b:3d:a0:07:52:c8:b7:71:30:71:fb:c3:a7:fa:
+                    61:f6:b4:28:be:9e:da:8b:8b:70:dd:8e:d0:a5:1a:
+                    00:70:1c:39:e1:cf:64:f8:ec:b4:83:b9:2b:67:fa:
+                    4d:ae:30:84:2f:2c:9d:6c:77:7e:09:95:43:77:6b:
+                    e1:9d:2b:c9:89:d9:a9:e5:8f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                B7:F0:DB:5F:BA:CC:10:6D:A6:64:62:10:84:A5:C9:39:4C:3C:27:86
+            X509v3 Authority Key Identifier: 
+                keyid:B7:F0:DB:5F:BA:CC:10:6D:A6:64:62:10:84:A5:C9:39:4C:3C:27:86
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta10/CN=localhost/emailAddress=ta10
+                serial:86:F1:45:12:31:C7:2B:2A
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        5b:6d:71:b8:4e:e3:27:06:d9:2a:47:ab:21:a3:df:94:a9:d8:
+        62:f1:6a:97:33:cc:1c:52:55:9a:f8:ec:6d:b4:91:17:4d:2a:
+        0e:03:b4:4b:00:83:10:8e:12:c1:05:67:56:9a:30:90:91:ad:
+        8b:dc:0a:eb:3f:28:5d:f9:d4:87:0d:f7:3a:5a:f6:47:52:9e:
+        af:4e:21:d4:2f:b8:40:4f:7f:81:1f:93:ca:bc:e6:04:c5:18:
+        65:5e:b1:dd:0b:3c:5e:3a:6f:48:e3:fc:b2:c8:37:8d:9f:14:
+        1b:a7:12:79:bb:2d:b9:fc:7a:01:ef:66:c6:d4:c2:44:01:49:
+        23:a9
+-----BEGIN CERTIFICATE-----
+MIIDYDCCAsmgAwIBAgIJAIbxRRIxxysqMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQ0wCwYDVQQLEwR0YTEwMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxEzARBgkqhkiG9w0BCQEWBHRhMTAwHhcNMTEwNDExMjIzNzU1WhcNMTQwMTA1
+MjIzNzU1WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEG
+A1UEBxMKTWVubG8gUGFyazENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMDES
+MBAGA1UEAxMJbG9jYWxob3N0MRMwEQYJKoZIhvcNAQkBFgR0YTEwMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQC2UENzZBJAJlQM+Wfkau0fGOVziRMPyV9ubsYF
+rSy+5Gv9xk/q828N9Bo0fwOXsKTRbpjSNvozXVE33o9bPaAHUsi3cTBx+8On+mH2
+tCi+ntqLi3DdjtClGgBwHDnhz2T47LSDuStn+k2uMIQvLJ1sd34JlUN3a+GdK8mJ
+2anljwIDAQABo4HlMIHiMB0GA1UdDgQWBBS38NtfuswQbaZkYhCEpck5TDwnhjCB
+sgYDVR0jBIGqMIGngBS38NtfuswQbaZkYhCEpck5TDwnhqGBg6SBgDB+MQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEGA1UEBxMKTWVubG8gUGFy
+azENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMDESMBAGA1UEAxMJbG9jYWxo
+b3N0MRMwEQYJKoZIhvcNAQkBFgR0YTEwggkAhvFFEjHHKyowDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOBgQBbbXG4TuMnBtkqR6sho9+Uqdhi8WqXM8wcUlWa
++OxttJEXTSoOA7RLAIMQjhLBBWdWmjCQka2L3ArrPyhd+dSHDfc6WvZHUp6vTiHU
+L7hAT3+BH5PKvOYExRhlXrHdCzxeOm9I4/yyyDeNnxQbpxJ5uy25/HoB72bG1MJE
+AUkjqQ==
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            d7:f1:84:58:4b:42:ce:33
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta11, CN=localhost/emailAddress=ta11
+        Validity
+            Not Before: Apr 11 22:37:55 2011 GMT
+            Not After : Jan  5 22:37:55 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta11, CN=localhost/emailAddress=ta11
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a3:c5:d4:23:f8:e8:a4:02:1f:38:cd:53:dc:7c:
+                    e8:3c:49:bd:14:c1:c7:a2:b7:00:7a:d2:d1:c8:01:
+                    7c:9b:f7:78:50:95:07:69:90:a0:7a:25:0f:55:55:
+                    f7:b2:33:ae:ae:66:64:5c:4c:86:66:e0:28:e2:63:
+                    8c:11:5f:ee:a4:af:77:86:c2:c0:18:0d:24:18:5f:
+                    26:ff:67:cc:f4:f9:7d:0c:e7:d7:0c:01:e8:85:57:
+                    f4:a8:d8:2c:f1:ec:2f:c7:8c:34:d4:3d:d3:1b:5c:
+                    2d:44:bd:d1:a6:35:d2:21:36:f9:31:ac:24:cb:ec:
+                    7b:70:c8:10:97:c8:8e:37:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                CE:A0:CF:69:A4:17:A0:54:BE:C3:CB:28:70:86:6A:BD:3B:DE:E4:CC
+            X509v3 Authority Key Identifier: 
+                keyid:CE:A0:CF:69:A4:17:A0:54:BE:C3:CB:28:70:86:6A:BD:3B:DE:E4:CC
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta11/CN=localhost/emailAddress=ta11
+                serial:D7:F1:84:58:4B:42:CE:33
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        89:34:9b:f9:55:53:63:83:82:0e:d0:f1:e5:0c:e3:4e:4b:2f:
+        54:20:2b:70:00:56:08:b4:18:88:59:e2:66:3e:5c:b6:0a:74:
+        16:bc:43:61:35:1e:df:e5:f6:f6:7e:de:87:18:61:b7:70:b0:
+        93:e8:5a:19:1d:01:a7:43:ca:38:ea:d2:e2:75:0e:3e:d2:b5:
+        91:57:1e:30:29:aa:2a:26:53:1b:9e:56:ad:61:41:3c:04:bb:
+        a5:af:da:75:63:5e:bb:31:21:f9:4c:dc:d0:c2:4c:90:07:45:
+        ed:32:0d:c0:c8:e9:6f:72:b5:ae:19:f2:88:9e:50:5c:5a:34:
+        47:a9
+-----BEGIN CERTIFICATE-----
+MIIDYDCCAsmgAwIBAgIJANfxhFhLQs4zMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQ0wCwYDVQQLEwR0YTExMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxEzARBgkqhkiG9w0BCQEWBHRhMTEwHhcNMTEwNDExMjIzNzU1WhcNMTQwMTA1
+MjIzNzU1WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEG
+A1UEBxMKTWVubG8gUGFyazENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMTES
+MBAGA1UEAxMJbG9jYWxob3N0MRMwEQYJKoZIhvcNAQkBFgR0YTExMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQCjxdQj+OikAh84zVPcfOg8Sb0UwceitwB60tHI
+AXyb93hQlQdpkKB6JQ9VVfeyM66uZmRcTIZm4CjiY4wRX+6kr3eGwsAYDSQYXyb/
+Z8z0+X0M59cMAeiFV/So2Czx7C/HjDTUPdMbXC1EvdGmNdIhNvkxrCTL7HtwyBCX
+yI43GQIDAQABo4HlMIHiMB0GA1UdDgQWBBTOoM9ppBegVL7Dyyhwhmq9O97kzDCB
+sgYDVR0jBIGqMIGngBTOoM9ppBegVL7Dyyhwhmq9O97kzKGBg6SBgDB+MQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEGA1UEBxMKTWVubG8gUGFy
+azENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMTESMBAGA1UEAxMJbG9jYWxo
+b3N0MRMwEQYJKoZIhvcNAQkBFgR0YTExggkA1/GEWEtCzjMwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOBgQCJNJv5VVNjg4IO0PHlDONOSy9UICtwAFYItBiI
+WeJmPly2CnQWvENhNR7f5fb2ft6HGGG3cLCT6FoZHQGnQ8o46tLidQ4+0rWRVx4w
+KaoqJlMbnlatYUE8BLulr9p1Y167MSH5TNzQwkyQB0XtMg3AyOlvcrWuGfKInlBc
+WjRHqQ==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/ro_data/signing_certs/produced/keys/cs1_ta7_reqpass_key.pem	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7BD624221BDD7236
+
+gNvIPXGF51x/X0fkeOqJiLQ+q18lZ3RdASIO/pLyi9pe7XTUzzmG7ZJbvuP57h1u
+e+yYSOGINEHZ7jaLHj3oAg/veNnB5jsJ0XXHOAV/E2HgmW24GEcLZpk73MBx9tdE
+Wp9v9yVgapjivwSKd8g28Pp/+yaeLIaghMtN02+M35X7q0vAdOlo3XX4iRiiGu7q
+EJGK+1TvVe+h+w5/Yo6n3I5OE8epRaFPk818s5FsHPBr1hAXgxv0GU3B9efZRaP8
+TVno7YRYfA+wKJQLbHv2y8TpkjvrwtUgeCF4qMrzOvtFECof5kXuBEzEntbSgAO3
+cCmoj87iUl1DFRgdWz0dacJk0XOOZD/1I2VhBBE5PLBBLMyiNNR+z4Sij21KkLa3
+5vrVWfHM9H8w6fQoCa6uOwt2DyeX5uukhGzqxu+JD2xDQ3oZjlEFaNqdNzIcacKd
+W2+yor1knPVKYAiOB/eqRAuGZ1XSlCyf7FVC+6JyBeSvrCxfGoZLo2tY9eKbJHxK
+BOWT55a1cXvkU8TizCd/5el2SDM11uFyGEEJcUiZoLhZL2nPXQtwbvtNQFJB9i7O
+mIF+ypcvVMynxSBroDDE9n/TTdHosLHNiCYEGRkexdwHen4d4KKpOANEmIMfneR3
+nvosZ7smOJzujtxu002rgay1Ud/RBbv/wwThi53/xmRCDtESAjdLdQSYZ0JQS9zq
+l5mvWFV5JoWRp5d18Wv9N9KqXizrCg2OFH2wwkUajwKykruNj4aFcIPrDr/d40wF
+fq5D7MKIXO/H8KIzWc0usYOlonRqJhMIyV8eyLK4RkU=
+-----END RSA PRIVATE KEY-----
--- a/src/tests/run.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/tests/run.py	Wed Aug 14 11:12:35 2013 +0530
@@ -214,14 +214,14 @@
         return suite_list
 
 def usage():
-        print >> sys.stderr, "Usage: %s [-cghptv] [-b filename] [-o regexp]" \
-                % sys.argv[0]
-        print >> sys.stderr, "       %s [-chptvx] [-b filename] [-s regexp] "\
+        print >> sys.stderr, "Usage: %s [-ghptv] [-c format] [-b filename] "\
                 "[-o regexp]" % sys.argv[0]
+        print >> sys.stderr, "       %s [-hptvx] [-c format] [-b filename] "\
+                "[-s regexp] [-o regexp]" % sys.argv[0]
         print >> sys.stderr, \
 """   -a <dir>       Archive failed test cases to <dir>/$pid/$testcasename
    -b <filename>  Baseline filename
-   -c             Collect code coverage data
+   -c <format>    Collect code coverage data in xml or html format
    -d             Show debug output, including commands run, and outputs
    -f             Show fail/error information even when test is expected to fail
    -g             Generate result baseline
@@ -239,6 +239,43 @@
 """
         sys.exit(2)
 
+def generate_coverage(cov_format, includes, omits, dest):
+        if cov_format == "html":
+                cov_option = "-d"
+                cov_dest = dest + "_html"
+        elif cov_format == "xml":
+                cov_option = "-o"
+                cov_dest = dest + ".xml"
+        else:
+                raise Exception("Unsupported coverage format")
+
+        cmd = ["coverage", cov_format]
+        if includes and len(includes):
+            cmd.extend(["--include", ",".join(includes)])
+        if omits and len(omits):
+            cmd.extend(["--omit", ",".join(omits)])
+        cmd.extend([cov_option, cov_dest])
+
+        print >> sys.stderr, "Generating coverage report via: ", " ".join(cmd)
+        if subprocess.Popen(cmd).wait() != 0:
+                raise Exception("Failed to generate coverage report!")
+
+        # The coverage data file and report are most likely owned by
+        # root, if a true test run was performed.  Make the files owned
+        # by the owner of the test directory, so they can be easily
+        # removed.
+        try:
+                uid, gid = os.stat(".")[4:6]
+                os.chown(cov_dest, uid, gid)
+                if cov_format == "html":
+                        for f in os.listdir(cov_dest):
+                                os.chown("%s/%s" % (cov_dest, f), uid, gid)
+        except EnvironmentError:
+                pass
+
+
+                
+
 if __name__ == "__main__":
         # Make all warnings be errors.
         warnings.simplefilter('error')
@@ -251,7 +288,7 @@
                 # If you add options here, you need to also update setup.py's
                 # test_func to include said options.
                 #
-                opts, pargs = getopt.getopt(sys.argv[1:], "a:cdfghj:pqtuvxb:o:s:z:",
+                opts, pargs = getopt.getopt(sys.argv[1:], "a:c:dfghj:pqtuvxb:o:s:z:",
                     ["generate-baseline", "parseable", "port", "timing",
                     "verbose", "baseline-file", "only"])
         except getopt.GetoptError, e:
@@ -280,6 +317,7 @@
                         output = OUTPUT_PARSEABLE
                 if opt == "-c":
                         do_coverage = True
+                        coverage_format = arg
                 if opt == "-d":
                         pkg5unittest.g_debug_output = True
                 if opt == "-f":
@@ -313,6 +351,7 @@
                         jobs = int(arg)
                 if opt == "-q":
                         quiet = True
+
         if (bailonfail or startattest) and generate:
                 usage()
         if quiet and (output != OUTPUT_DOTS):
@@ -329,6 +368,9 @@
                 cov.stop()
                 shutil.rmtree(covdir)
                 cov = None
+        elif not coverage_format in ("xml", "html"):
+                print >> sys.stderr, "-c <format> must be xml or html"
+                usage()
 
         # Allow relative archive dir, but first convert it to abs. paths.
         if archive_dir is not None:
@@ -467,31 +509,32 @@
                 subprocess.Popen(["coverage", "combine"], env=newenv).wait()
                 os.rename("%s/pkg5" % covdir, ".coverage")
                 shutil.rmtree(covdir)
-                vp = pkg5unittest.g_proto_area + "/usr/lib/python2.6/vendor-packages"
+
                 omits = [
                     # These mako templates fail.
-                    "*etc_pkg_*mako",
+                    "*etc_pkg_*mako", "_depot_conf_mako",
                     # Complex use of module importer makes this fail.
                     "*sysrepo_p5p.py"
                 ]
-                print >> sys.stderr, "Generating html coverage report"
-                cmd = ["coverage", "html", "--omit", ",".join(omits),
-                    "-d", "htmlcov"]
-                print >> sys.stderr, "# %s" % " ".join(cmd)
-                if subprocess.Popen(cmd).wait() != 0:
-                        print >> sys.stderr, \
-                            "Failed to generate coverage report!"
-                        exitval = 1
+                proto = ["{0}/*".format(pkg5unittest.g_proto_area)]
+
+                try:
+                    generate_coverage(coverage_format,
+                        proto,
+                        omits, "cov_proto")
+                    generate_coverage(coverage_format, None,
+                        proto + omits, "cov_tests")
+                except Exception, e:
+                    print >> sys.stderr, e                        
+                    exitval = 1
+
                 # The coverage data file and report are most likely owned by
                 # root, if a true test run was performed.  Make the files owned
                 # by the owner of the test directory, so they can be easily
                 # removed.
                 try:
                         uid, gid = os.stat(".")[4:6]
-                        os.chown("htmlcov", uid, gid)
                         os.chown(".coverage", uid, gid)
-                        for f in os.listdir("htmlcov"):
-                                os.chown("htmlcov/%s" % f, uid, gid)
                 except EnvironmentError:
                         pass
         sys.exit(exitval)
--- a/src/um/pkg-update	Thu Jul 18 09:40:49 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-#!/bin/ksh
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-# A rather simple SMF method script for
-# svc:/application/pkg/update:default
-# It's sole purpose is to add or remove a crontab entry
-
-. /lib/svc/share/smf_include.sh
-
-FMRI="svc:/application/pkg/update:default"
-REFRESH_PROG="/usr/lib/update-manager/update-refresh.sh"
-
-# Given the exit status of a command, an integer, 0 if the command completed
-# without errors. If the command exited with errors we degrade the
-# state of this service into maintenance mode. If a 3rd argument is presented
-# we don't degrade the service. We also log an error message as passed into
-# this function.
-#
-function check_failure { # integer exit status, error message to display, be fatal
-
-	typeset RESULT=$1
-	typeset ERR_MSG=$2
-	typeset NON_FATAL=$3
-
-	if [ $RESULT -ne 0 ] ; then
-	    print_log "Error: $ERR_MSG"
-	    if [ -z "${NON_FATAL}" ] ; then
-		print_log "Moving service $FMRI to maintenance mode."
-	        svcadm mark maintenance $FMRI
-	    fi
-	fi
-
-}
-
-# A function we use to emit output. Right now, this goes to syslog via logger(1)
-# but it would be much nicer to be able to print it to the svc log file for
-# each individual service instance - tricky because we're being called from
-# cron, most of the time and are detached from smf. Working around this by
-# appending to the $LOG file
-function print_log { # message to display
-	logger -t update-manager -p daemon.notice $*
-}
-
-function add_refresh_cronjob {
-	# Call intermittently  
-	SCHEDULE="30 0,9,12,18,21 * * *"
-
-	# adding a cron job is essentially just looking for an existing entry,
-	# removing it, and appending a new one. Neato.
-	crontab -l | grep -v "${REFRESH_PROG}" \
-	    > /tmp/saved-crontab.$$
-
-	echo "${SCHEDULE} ${REFRESH_PROG}" \
-	    >> /tmp/saved-crontab.$$
-
-	crontab /tmp/saved-crontab.$$
-	check_failure $? "Unable to add cron job!"
-
-	rm /tmp/saved-crontab.$$
-	return 0
-}
-
-function remove_refresh_cronjob {
-
-	crontab -l | grep -v "${REFRESH_PROG}" \
-	    > /tmp/saved-crontab.$$
-
-	crontab /tmp/saved-crontab.$$
-	check_failure $? "Unable to unschedule snapshots for $FMRI"
-
-	rm /tmp/saved-crontab.$$
-
-	# finally, check our status before we return
-	STATE=$(svcprop -p restarter/state $FMRI)
-	if [ "${STATE}" == "maintenance" ] ; then
-	    STATE=1
-	else
-	    STATE=0
-	fi
-}
-
-case $SMF_METHOD in
-"start")
-	add_refresh_cronjob
-	;;
-"stop")
-	remove_refresh_cronjob
-	;;
-*)
-	echo "Command line invocation of ${0} unsupported."
-	echo "This script is intended for smf(5) invocation only"
-	exit $SMF_EXIT_ERR_NOSMF
-	;;
-esac
-exit $SMF_EXIT_OK
--- a/src/um/update-refresh.sh	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/um/update-refresh.sh	Wed Aug 14 11:12:35 2013 +0530
@@ -77,9 +77,9 @@
 let dither=dither/32767
 sleep $dither
 
-image_dir=$(svcprop -p update/image_dir $fmri || echo "/")
+image_dir=/
 pkg -R $image_dir refresh -q 2>/dev/null
 
 # Check and cache whether updates are available
-/usr/lib/pm-checkforupdates -R $image_dir --nice
+/usr/lib/pm-checkforupdates --nice
 exit 0
--- a/src/updatemanager.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/updatemanager.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import getopt
@@ -38,6 +38,7 @@
 except ImportError:
         sys.exit(1)
 
+import pkg.client.api as api
 import pkg.client.progress as progress
 import pkg.gui.enumerations as enumerations
 import pkg.gui.installupdate as installupdate
@@ -64,8 +65,14 @@
                 global_settings.client_name = gui_misc.get_um_name()
                 self.api_lock = nrlock.NRLock()
                 self.image_dir_arg = image_directory
+                self.exact_match = True
                 if self.image_dir_arg == None:
-                        self.image_dir_arg = gui_misc.get_image_path()
+                        self.image_dir_arg, self.exact_match = \
+                            api.get_default_image_root()
+                if not self.exact_match:
+                        if debug:
+                                print >> sys.stderr, ("Unable to get the image directory")
+                        sys.exit(enumerations.UPDATES_UNDETERMINED)
                 self.application_path = application_path
                 self.gconf = pmgconf.PMGConf()
                 try:
--- a/src/updatemanagernotifier.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/updatemanagernotifier.py	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -62,7 +62,6 @@
 SHOW_NOTIFY_ICON_DEFAULT = True
 IMAGE_DIRECTORY_DEFAULT = "/"
 LASTCHECK_DIR_NAME = os.path.join(os.path.expanduser("~"),'.updatemanager/notify')
-IMAGE_DIR_COMMAND = "svcprop -p update/image_dir svc:/application/pkg/update"
 CHECKFOR_UPDATES = "/usr/lib/pm-checkforupdates"
 UPDATEMANAGER = "pm-updatemanager"
 
@@ -316,14 +315,9 @@
                 gobject.timeout_add(random_delay * 1000, self.check_for_updates)
 
         def check_for_updates(self):
-                image_directory = os.popen(IMAGE_DIR_COMMAND).readline().rstrip()
-                if debug == True:
-                        print "image_directory: %s" % image_directory
-                if len(image_directory) == 0:
-                        image_directory = IMAGE_DIRECTORY_DEFAULT
                 proc = subprocess.Popen([CHECKFOR_UPDATES,
                             '--nice', '--checkupdates-cache',
-                            '--image-dir', image_directory],
+                            '--image-dir', IMAGE_DIRECTORY_DEFAULT],
                             stdout=subprocess.PIPE)
 
                 output = proc.communicate()[0].strip()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/apache2/depot/depot.conf.mako	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,256 @@
+<%doc>
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# This file is the template for an Apache configuration that serves pkg(5)
+# repositories.  On its own, it can be used to render a fragment that can be
+# dropped into an Apache conf.d directory, or it can be referenced from
+# a more complete httpd.conf template via an include directive.
+#
+</%doc><%
+import urllib
+%>
+RewriteEngine on
+RewriteLog "${log_dir}/rewrite.log"
+RewriteLogLevel 0
+
+# We need to allow these as they're encoded in the package/manifest names
+# when looking up v4 repositories
+AllowEncodedSlashes On
+# The default of 500 MaxKeepAliveRequests is too low to be useful.
+MaxKeepAliveRequests 10000
+
+<%doc>
+# All of our rules specify the NE flag, 'noescape', that is
+# we don't want any rewritten URLs being decoded en-route through
+# the set of RewriteRule directives.
+#
+
+# For all RewriteRule directives below, we allow sroot to specify
+# a server-root beneath which we should operate.
+</%doc>
+<%
+
+repo_prefixes = set()
+root = context.get("sroot")
+runtime_dir = context.get("runtime_dir")
+
+for pub, repo_path, repo_prefix in pubs:
+        repo_prefixes.add(repo_prefix)
+context.write("# per-repository versions and publishers responses\n")
+
+for repo_prefix in repo_prefixes:
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)sversions/0 "
+            "/%(root)sversions/0/index.html [PT,NE]\n" % locals())
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)spublisher/0 "
+            "/%(root)s%(repo_prefix)spublisher/1/index.html [PT,NE]\n" %
+            locals())
+%>
+
+<%doc>
+#
+# Rules to redirect default publisher requests into the publisher-specific
+# rules below.  Publisher and versions responses were handled above.
+#
+</%doc>
+# Rules to deal with responses for default publishers
+#
+<%
+        for pub, repo_path, repo_prefix in default_pubs:
+                if pub == None:
+                        continue
+                root = context.get("sroot")
+                # manifest rules need to use %{THE_REQUEST} undecoded
+                # URI from mod_rewrite. However, since %{THE_REQUEST} is the
+                # original request, we can't simply rewrite the URI
+                # here to add the publisher, then let the other manifest rules
+                # pick up the trail, so we need to do more work here,
+                # basically duplicating how we deal with manifest responses
+                # that have got a publisher included in the URI.
+                context.write(
+                    "RewriteRule ^/%(root)s%(repo_prefix)smanifest/0/.*$ "
+                    "%%{THE_REQUEST} [NE,C]\n" % locals())
+                context.write("RewriteRule ^GET\ "
+                    "/%(root)s%(repo_prefix)smanifest/0/([^@]+)@([^\ ]+)(\ HTTP/1.1)$ "
+                    "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/pkg/$1/$2 [NE,PT,C]\n"
+                    % locals())
+                context.write(
+                    "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/(.*)$ "
+		    "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/$1 [NE,L]\n"
+                    % locals())
+
+                # file responses require more work, so rewrite to
+                # a URI that will get further rewrites later.
+                context.write("RewriteRule "
+                    "^/%(root)s%(repo_prefix)sfile/(.*$) "
+                    "/%(root)s%(repo_prefix)s%(pub)s/file/$1 [NE]\n"
+                    % locals())
+                # for catalog parts, we can easily access the file with one
+                # RewriteRule, so do that, then PT to the Alias directive.
+                context.write("RewriteRule "
+                    "^/%(root)s%(repo_prefix)scatalog/1/(.*$) "
+                    "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/catalog/$1 [NE,PT]\n"
+                    % locals())
+%>
+
+# Write per-publisher rules for publisher, version, file and manifest responses
+% for pub, repo_path, repo_prefix in pubs:
+        <%doc>
+        # Point to our local versions/0 response or
+        # publisher-specific publisher/1, response, then stop.
+        </%doc>
+# Serve our static versions and publisher responses
+<%
+        root = context.get("sroot")
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/versions/0 "
+            "%%{DOCUMENT_ROOT}/%(root)sversions/0/index.html [L,NE]\n" % locals())
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/publisher/0 "
+            "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/publisher/1/index.html [L,NE]\n" %
+            locals())
+
+%><%doc>
+        # Modify the catalog, file and manifest URLs, then 'passthrough' (PT),
+        # letting the Alias directives below serve the file.
+        </%doc>
+<%
+        root = context.get("sroot")
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/catalog/1/(.*)$ "
+            "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/catalog/$1 [NE,PT]" %
+            locals())
+        %><%doc>
+        # file responses are a little tricky - we need to index
+        # the first two characters of the filename and use that
+        # as an index into the directory of filenames.
+        # (omitting sroot and repo_prefix here, for brevity)
+        # eg. the request
+        # http://localhost:10000/pkg5-nightly/file/1/87ad645695abb22b2959f73d22022c5cffeccb13
+        # gets rewritten as:
+        # http://localhost:10000/pkg5-nightly/publisher/pkg5-nightly/file/87/87ad645695abb22b2959f73d22022c5cffeccb13
+        </%doc>
+<%
+        root = context.get("sroot")
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/file/1/(..)(.*)$ "
+            "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/file/$1/$1$2 [NE,PT]\n"
+            % locals())
+        %><%doc>
+        # We need to use %THE_REQUEST here to get the undecoded
+        # URI from mod_rewrite.  Hang on to your lunch.
+        # We chain the rule that produces THE_REQUEST to the
+        # following rule which picks apart the original http
+        # request to separate the package name from the package
+        # version.
+        #
+        # That is, mod_rewrite sees the pkg client asking for
+        # the initial decoded URI:
+        #  '/pkg5-nightly/manifest/0/package/[email protected],5.11-0.159:20110308T011843Z'
+        #
+        # which comes from the HTTP request:
+        #  'GET /pkg5-nightly/manifest/0/package%[email protected]%2C5.11-0.159%3A20110308T011843Z HTTP/1.1'
+        #
+        # which we eventually rewrite as:
+        #  -> '/pkg5-nightly/publisher/pkg5-nightly/pkg/package%2Fsysrepo/0.5.11%2C5.11-0.159%3A20110308T011843Z'
+        </%doc>
+<%
+        root = context.get("sroot")
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/manifest/0/.*$ "
+            "%%{THE_REQUEST} [NE,C]\n" % locals())
+
+        context.write("RewriteRule ^GET\ "
+            "/%(root)s%(repo_prefix)s%(pub)s/manifest/0/([^@]+)@([^\ ]+)(\ HTTP/1.1)$ "
+            "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/pkg/$1/$2 [NE,PT,C]\n"
+            % locals())
+        context.write(
+            "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/(.*)$ "
+            "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/$1 [NE,L]\n"
+            % locals())
+%>
+% endfor pub
+
+<%
+paths = set()
+root = context.get("sroot")
+for pub, repo_path, repo_prefix in pubs:
+        paths.add((repo_path, repo_prefix))
+        context.write(
+            "Alias /%(root)s%(repo_prefix)s%(pub)s %(repo_path)s\n" %
+            locals())
+for repo_path, repo_prefix in paths:
+        context.write("# an alias to serve %(repo_path)s content.\n"
+            "<Directory \"%(repo_path)s\">\n"
+            "    AllowOverride None\n"
+            "    Order allow,deny\n"
+            "    Allow from all\n"
+            "</Directory>\n" % locals())
+%>
+
+# Our versions response.
+RewriteRule ^/${sroot}.*[/]?versions/0/?$ %{DOCUMENT_ROOT}/versions/0/index.html [L]
+# allow for 'OPTIONS * HTTP/1.0' requests
+RewriteCond %{REQUEST_METHOD} OPTIONS [NC]
+RewriteRule \* - [L]
+
+<%
+for repo_prefix in repo_prefixes:
+        if root:
+                context.write(
+                    "# Since we're running as a fragment within an existing\n"
+                    "# web server, we take a portion of the namespace for ourselves\n")
+                context.write(
+                    "Alias /%(root)s %(runtime_dir)s/htdocs/%(root)s\n" %
+                     locals())
+                context.write(
+                    "<Directory \"%(runtime_dir)s/htdocs\">\n"
+                    "    AllowOverride None\n"
+                    "    Order allow,deny\n"
+                    "    Allow from all\n"
+                    "</Directory>\n" % locals())
+%>
+
+# These location matches are based on the final Rewrite paths for file,
+# manifest, catalog and publisher responses.
+<LocationMatch ".*/file/../[a-zA-Z0-9]+$">
+        Header set Cache-Control "must-revalidate, no-transform, max-age=31536000"
+        Header set Content-Type application/data
+</LocationMatch>
+<LocationMatch ".*/publisher/.*/pkg/.*">
+        Header set Cache-Control "must-revalidate, no-transform, max-age=31536000"
+        Header set Content-Type text/plain;charset=utf-8
+</LocationMatch>
+<LocationMatch ".*/catalog/catalog.*.C">
+        Header set Cache-Control "must-revalidate, no-transform, max-age=86400"
+        Header set Content-Type text/plain;charset=utf-8
+</LocationMatch>
+<LocationMatch ".*/catalog.attrs">
+        Header set Cache-Control no-cache
+</LocationMatch>
+<LocationMatch ".*/publisher/\d/.*">
+        Header set Cache-Control "must-revalidate, no-transform, max-age=31536000"
+        Header set Content-Type application/vnd.pkg5.info
+</LocationMatch>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/apache2/depot/depot_httpd.conf.mako	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,458 @@
+<%doc>
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# This file is the template for the Apache configuration that serves pkg(5)
+# repositories.
+#
+</%doc>
+<%
+        import os.path
+        import urllib
+        context.write("""
+#
+# This is an automatically generated file for IPS repositories, and
+# should not be modified directly.  Changes made to this file will be
+# overwritten the next time svc:/application/pkg/server:default is
+# refreshed or restarted.  /etc/pkg/depot/conf.d can be used for user
+# customizations.
+#
+""")
+%>
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path.  If you point
+# ServerRoot at a non-local disk, be sure to point the LockFile directive
+# at a local disk.  If you wish to share the same ServerRoot for multiple
+# httpd daemons, you will need to change at least LockFile and PidFile.
+#
+ServerRoot "/usr/apache2/2.2"
+PidFile "${runtime_dir}/../depot_httpd.pid"
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+# Listen 12.34.56.78:80
+
+Listen ${host}:${port}
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to include a `LoadModule' line so that the directives contained in it
+# are actually available _before_ they are used.
+#
+
+LoadModule authz_host_module libexec/64/mod_authz_host.so
+LoadModule log_config_module libexec/64/mod_log_config.so
+LoadModule ssl_module libexec/64/mod_ssl.so
+LoadModule mime_module libexec/64/mod_mime.so
+LoadModule dir_module libexec/64/mod_dir.so
+LoadModule alias_module libexec/64/mod_alias.so
+LoadModule rewrite_module libexec/64/mod_rewrite.so
+LoadModule headers_module libexec/64/mod_headers.so
+LoadModule env_module libexec/64/mod_env.so
+LoadModule wsgi_module libexec/64/mod_wsgi-2.6.so
+LoadModule cache_module libexec/64/mod_cache.so
+LoadModule disk_cache_module libexec/64/mod_disk_cache.so
+LoadModule deflate_module libexec/64/mod_deflate.so
+
+
+# Turn on deflate for file types that support it
+AddOutputFilterByType DEFLATE text/html application/javascript text/css text/plain
+# We only alias a specific script, not all files in ${template_dir}
+WSGIScriptAlias ${sroot}/depot ${template_dir}/depot_index.py
+
+# We set a 5 minute inactivity timeout: if no requests have been received in the
+# last 5 minutes and no requests are currently being processed, mod_wsgi shuts
+# down the Python interpreter. An exception is made for index-refresh
+# operations, which are allowed to run to completion by periodically sending
+# requests to the server during the course of the refresh.
+<%
+        test_proto = os.environ.get("PKG5_TEST_PROTO", None)
+        if test_proto:
+                context.write("""
+WSGIDaemonProcess pkgdepot processes=1 threads=21 user=pkg5srv group=pkg5srv display-name=pkg5_depot inactivity-timeout=300 python-path=%s/usr/lib/python2.6
+SetEnv PKG5_TEST_PROTO %s
+""" % (test_proto, test_proto))
+        else:
+                context.write("""
+WSGIDaemonProcess pkgdepot processes=1 threads=21 user=pkg5srv group=pkg5srv display-name=pkg5_depot inactivity-timeout=300
+""")
+%>
+WSGIProcessGroup pkgdepot
+WSGISocketPrefix ${runtime_dir}/wsgi
+# don't accept requests over 100k
+LimitRequestBody 102400
+# Set environment variables used by our wsgi application
+SetEnv PKG5_RUNTIME_DIR ${runtime_dir}
+SetEnv PKG5_CACHE_DIR ${cache_dir}
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User pkg5srv
+Group pkg5srv
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed.  This address appears on some server-generated pages, such
+# as error documents.  e.g. [email protected]
+#
+ServerAdmin [email protected]
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+# Workaround an Apache bug where IPv6 addresses in server names are not accepted
+<%
+        servername = context.get("host")
+        serverport = context.get("port")
+        if ":" not in servername:
+                context.write("ServerName %(host)s:%(port)s\n" %
+                    {"host": servername, "port": serverport})
+%>
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "${runtime_dir}/htdocs"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+# First, we configure the "default" to be a very restrictive set of
+# features.
+#
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+    Order deny,allow
+    Deny from all
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+<Directory "${runtime_dir}/htdocs">
+    #
+    # Possible values for the Options directive are "None", "All",
+    # or any combination of:
+    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+    #
+    # Note that "MultiViews" must be named *explicitly* --- "Options All"
+    # doesn't give it to you.
+    #
+    # The Options directive is both complicated and important.  Please see
+    # http://httpd.apache.org/docs/2.2/mod/core.html#options
+    # for more information.
+    #
+    Options FollowSymLinks
+
+    #
+    # AllowOverride controls what directives may be placed in .htaccess files.
+    # It can be "All", "None", or any combination of the keywords:
+    #   Options FileInfo AuthConfig Limit
+    #
+    AllowOverride None
+
+    #
+    # Controls who can get stuff from this server.
+    #
+    Order allow,deny
+    Allow from all
+
+</Directory>
+
+# Allow access to wsgi scripts under ${template_dir}
+<Directory ${template_dir}>
+    SetHandler wsgi-script
+    WSGIProcessGroup pkgdepot
+    Options ExecCGI
+    Allow from all
+</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+    DirectoryIndex index.html
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</FilesMatch>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog "${log_dir}/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+<IfModule log_config_module>
+    #
+    # The following directives define some format nicknames for use with
+    # a CustomLog directive (see below).
+    #
+    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+    LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+    <IfModule logio_module>
+      # You need to enable mod_logio.c to use %I and %O
+      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+    </IfModule>
+
+    #
+    # The location and format of the access logfile (Common Logfile Format).
+    # If you do not define any access logfiles within a <VirtualHost>
+    # container, they will be logged here.  Contrariwise, if you *do*
+    # define per-<VirtualHost> access logfiles, transactions will be
+    # logged therein and *not* in this file.
+    #
+    CustomLog "${log_dir}/access_log" common
+
+    #
+    # If you prefer a logfile with access, agent, and referer information
+    # (Combined Logfile Format) you can use the following directive.
+    #
+    #CustomLog "/var/apache2/2.2/logs/access_log" combined
+</IfModule>
+
+#
+# DefaultType: the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# Note: The following must must be present to support
+#       starting without SSL on platforms with no /dev/random equivalent
+#       but a statically compiled-in mod_ssl.
+#
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+SSLSessionCache shmcb:${cache_dir}/ssl_scache(512000)
+</IfModule>
+
+
+% if allow_refresh:
+# When set to true, we allow admin/0 operations to rebuild the index
+SetEnv PKG5_ALLOW_REFRESH true
+% endif
+
+% if int(cache_size) > 0:
+CacheRoot ${cache_dir}
+# The levels and length of the cache directories can
+# be small here, as ZFS is good at dealing with directories
+# containing many files.
+CacheDirLevels 1
+CacheDirLength 2
+# A 44mb seems like a reasonable size for the largest
+# file we will choose to cache.
+CacheMaxFileSize 45690876
+% endif
+
+# Rules to serve static content directly from the file-repositories.
+<%include file="/depot.conf.mako"/>
+# with no URL-path, we show an index of the available repositories.
+RewriteRule ^${sroot}[/]?$ ${sroot}/depot/repos.shtml [NE,PT]
+
+<%
+        path_info = set()
+        root = context.get("sroot")
+        context.write("# the repositories our search app should index.\n")
+        for pub, repo_path, repo_prefix in pubs:
+                path_info.add((repo_path, repo_prefix.rstrip("/")))
+        for repo_path, repo_prefix in path_info:
+                context.write(
+                    "SetEnv PKG5_REPOSITORY_%(repo_prefix)s %(repo_path)s\n" %
+                    locals())
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)s/[/]?$ "
+                    "%(root)s/depot/%(repo_prefix)s/ [NE,PT]\n" %
+                    locals())
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)s/([a-z][a-z])[/]?$ "
+                    "%(root)s/depot/%(repo_prefix)s/$1 [NE,PT]\n" %
+                    locals())
+%>
+% for pub, repo_path, repo_prefix in pubs:
+% if int(cache_size) > 0:
+CacheEnable disk /${root}${repo_prefix}${pub}/file
+CacheEnable disk /${root}${repo_prefix}${pub}/manifest
+% endif
+<%
+        #
+        # A series of rules to redirect into /depot where the WSGI application
+        # is mounted to serve requests for the BUI application.
+        #
+        root = context.get("sroot")
+        # search responses
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/search/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/search/$1 [NE,PT]\n" %
+            locals())
+        # admin responses
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/admin/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/admin/$1 [NE,PT]\n" %
+            locals())
+        # info responses
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/info/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/info/$1 [NE,PT]\n" %
+            locals())
+        # p5i responses
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/p5i/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/p5i/$1 [NE,PT]\n" %
+            locals())
+        # Deal with languages - any two letter language code.
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/([a-z][a-z])/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/$1/$2 [NE,PT]\n" %
+            locals())
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/([a-z][a-z])$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/$1/ [NE,PT]\n" %
+            locals())
+        # Deal with just the publisher
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s[/]?$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/ [NE,PT]\n" %
+            locals())
+        # redirect themes requests into the CherryPy code
+        context.write("RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/_themes/(.*)$ "
+            "%(root)s/depot/%(repo_prefix)s%(pub)s/_themes/$1 [NE,PT]\n" %
+            locals())
+%>
+% endfor pub
+RewriteRule ^${sroot}/_themes/(.*)$ ${sroot}/depot/_themes/$1 [NE,PT]
+RewriteRule ^${sroot}/repos.shtml$ ${sroot}/depot/repos.shtml [NE,PT]
+
+% for pub, repo_path, repo_prefix in default_pubs:
+<%
+        #
+        # When publisher names are not included in the request, we use the
+        # default publisher set in the repository.
+        #
+        root = context.get("sroot")
+        context.write("# Map the default publishers for %(repo_path)s to "
+            "%(pub)s\n" % locals())
+
+        if "pub" != None:
+                # search
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)ssearch/(.*)$ "
+                    "%(root)s/depot/%(repo_prefix)s%(pub)s/search/$1 [NE,PT]\n"
+                    % locals())
+                # admin
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)sadmin/(.*)$ "
+                    "%(root)s/depot/%(repo_prefix)s%(pub)s/admin/$1 [NE,PT]\n"
+                    % locals())
+                # info
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)sinfo/(.*)$ "
+                    "%(root)s/depot/%(repo_prefix)s%(pub)s/info/$1 [NE,PT]\n"
+                    % locals())
+                # p5i
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)sp5i/(.*)$ "
+                    "%(root)s/depot/%(repo_prefix)s%(pub)s/p5i/$1 [NE,PT]\n"
+                    % locals())
+                # Deal with languages - any two-letter language code.
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)s([a-z][a-z])/(.*)$ "
+                        "%(root)s/depot/%(repo_prefix)s%(pub)s/$1/$2 [NE,PT]\n" %
+                        locals())
+                # redirect themes requests into the CherryPy code
+                context.write("RewriteRule ^/%(root)s%(repo_prefix)s_themes/(.*)$ "
+                    "%(root)s/depot/%(repo_prefix)s%(pub)s/_themes/$1 [NE,PT]\n" %
+                    locals())
+%>
+% endfor pub
+
+# Don't cache search requests.
+<LocationMatch ".*/search/\d/.*">
+        Header set Content-Type "text/plain;charset=utf-8"
+        Header set Cache-Control no-cache
+</LocationMatch>
+
+<%
+        if not test_proto:
+                context.write("""
+# Include any site-specific configuration
+Include /etc/pkg/depot/conf.d/*.conf
+""")
+%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/apache2/depot/depot_index.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,760 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+
+import cherrypy
+import hashlib
+import httplib
+import logging
+import mako
+import os
+import re
+import sys
+import threading
+import time
+import traceback
+import urllib
+import Queue
+
+import pkg.p5i
+import pkg.server.api
+import pkg.server.repository as sr
+import pkg.server.depot as sd
+import pkg.server.face as face
+
+# redirecting stdout for proper WSGI portability
+sys.stdout = sys.stderr
+
+# a global dictionary containing lists of sr.Repository objects, keyed by
+# repository prefix (not publisher prefix).
+repositories = {}
+
+# a global dictionary containing lists of DepotBUI objects, keyed by repository
+# prefix.
+depot_buis = {}
+
+# a lock used during server startup to ensure we don't try to index the same
+# repository at once.
+repository_lock = threading.Lock()
+
+import gettext
+gettext.install("/")
+
+# How often we ping the depot while long-running background tasks are running
+# this should be set to less than the mod_wsgi inactivity-timeout (since
+# pinging the depot causes activity, preventing mod_wsgi from shutting down the
+# Python interpreter.
+KEEP_BUSY_INTERVAL = 120
+
+class DepotException(Exception):
+        """Super class for all exceptions raised by depot_index."""
+        def __init__(self, request, message):
+                self.request = request
+                self.message = message
+                self.http_status = httplib.INTERNAL_SERVER_ERROR
+
+        def __str__(self):
+                return "%s: %s" % (self.message, self.request)
+
+class AdminOpsDisabledException(DepotException):
+        """An exception thrown when this wsgi application hasn't been configured
+        to allow admin/0 pkg(5) depot responses."""
+
+        def __init__(self, request):
+                self.request = request
+                self.http_status = httplib.FORBIDDEN
+
+        def __str__(self):
+                return "admin/0 operations are disabled. " \
+                    "See the config/allow_refresh SMF property. " \
+                    "Request was: %s" % self.request
+
+
+class AdminOpNotSupportedException(DepotException):
+        """An exception thrown when an admin request was made that isn't
+        supported by the http-depot."""
+
+        def __init__(self, request, cmd):
+                self.request = request
+                self.cmd = cmd
+                self.http_status = httplib.NOT_IMPLEMENTED
+
+        def __str__(self):
+                return "admin/0 operations of type %(type)s are not " \
+                    "supported by this repository. " \
+                    "Request was: %(request)s" % {"request": self.request,
+                    "type": self.cmd}
+
+
+class BackgroundTask(object):
+        """Allow us to process a limited set of threads in the background."""
+
+        def __init__(self, size=10, busy_url=None):
+                self.size = size
+                self.__q = Queue.Queue(self.size)
+                self.__thread = None
+                self.__running = False
+                self.__keep_busy_thread = None
+                self.__keep_busy = False
+                self.__busy_url = busy_url
+
+        def join(self):
+                """perform a Queue.join(), which blocks until all the tasks
+                in the queue have been completed."""
+                self.__q.join()
+
+        def unfinished_tasks(self):
+                """Return the number of tasks remaining in our Queue."""
+                return self.__q.unfinished_tasks
+
+        def put(self, task, *args, **kwargs):
+                """Schedule the given task for background execution if queue
+                isn't full.
+                """
+                if self.__q.unfinished_tasks > self.size - 1:
+                        raise Queue.Full()
+                self.__q.put_nowait((task, args, kwargs))
+                self.__keep_busy = True
+
+        def run(self):
+                """Run any background task scheduled for execution."""
+                while self.__running:
+                        try:
+                                try:
+                                        # A brief timeout here is necessary
+                                        # to reduce CPU usage and to ensure
+                                        # that shutdown doesn't wait forever
+                                        # for a new task to appear.
+                                        task, args, kwargs = \
+                                            self.__q.get(timeout=.5)
+                                except Queue.Empty:
+                                        continue
+                                task(*args, **kwargs)
+                                if hasattr(self.__q, "task_done"):
+                                        # Task is done; mark it so.
+                                        self.__q.task_done()
+                                        if self.__q.unfinished_tasks == 0:
+                                                self.__keep_busy = False
+                        except Exception, e:
+                                print("Failure encountered executing "
+                                    "background task %r." % self)
+
+        def run_keep_busy(self):
+                """Run our keep_busy thread, periodically sending a HTTP
+                request if the __keep_busy flag is set."""
+                while self.__running:
+                        # wait for a period of time, then ping our busy_url
+                        time.sleep(KEEP_BUSY_INTERVAL)
+                        if self.__keep_busy:
+                                try:
+                                        urllib.urlopen(self.__busy_url).close()
+                                except Exception, e:
+                                        print("Failure encountered retrieving "
+                                            "busy url %s: %s" %
+                                            (self.__busy_url, e))
+
+        def start(self):
+                """Start the background task thread. Since we configure
+                mod_wsgi with an inactivity-timeout, long-running background
+                tasks which don't cause new WSGI HTTP requests can
+                result in us hitting that inactivity-timeout. To prevent this,
+                while background tasks are running, we periodically send a HTTP
+                request to the server."""
+                self.__running = True
+                if not self.__thread:
+                        # Create and start a thread for the caller.
+                        self.__thread = threading.Thread(target=self.run)
+                        self.__thread.start()
+
+                        self.__keep_busy_thread = threading.Thread(
+                            target=self.run_keep_busy)
+                        self.__keep_busy_thread.start()
+
+
+class DepotBUI(object):
+        """A data object that pkg.server.face can use for configuration.
+        This object should look like a pkg.server.depot.DepotHTTP to
+        pkg.server.face, but it doesn't need to perform any operations.
+
+        pkg5_test_proto should point to a proto area where we can access
+        web resources (css, html, etc)
+        """
+
+        def __init__(self, repo, dconf, tmp_root, pkg5_test_proto=""):
+                self.repo = repo
+                self.cfg = dconf
+                self.tmp_root = tmp_root
+                # we hardcode these for the depot.
+                self.content_root = "%s/usr/share/lib/pkg" % pkg5_test_proto
+                self.web_root = "%s/usr/share/lib/pkg/web/" % pkg5_test_proto
+
+                # ensure we have the right values in our cfg, needed when
+                # creating DepotHTTP objects.
+                self.cfg.set_property("pkg", "content_root", self.content_root)
+                self.cfg.set_property("pkg", "pkg_root", self.repo.root)
+                face.init(self)
+
+
+class WsgiDepot(object):
+        """A WSGI application object that allows us to process search/1 and
+        certain admin/0 requests from pkg(5) clients of the depot.  Other
+        requests for BUI content are dealt with by instances of DepotHTTP, which
+        are created as necessary.
+
+        In the server-side WSGI environment, apart from the default WSGI
+        values, defined in PEP333, we expect the following:
+
+        PKG5_RUNTIME_DIR  A directory that contains runtime state, notably
+                          a htdocs/ directory.
+
+        PKG5_CACHE_DIR    Where we can store search indices for the repositories
+                          we're managing.
+
+        PKG5_REPOSITORY_* A colon-separated pair of values, in the form
+                          <repo_prefix>:<repo_root>.  <repo_prefix> is a unique
+                          alphanumeric prefix that maps to the given
+                          <repo_root>.  Many PKG5_REPOSITORY_* variables can be
+                          configured, possibly containing identical pkg5
+                          publishers.
+
+        PKG5_ALLOW_REFRESH Set to 'true', this determines whether we process
+                          admin/0 requests that have the query 'cmd=refresh' or
+                          'cmd=refresh-indexes'.
+
+                          If not true, we return a HTTP 503 response. Otherwise,
+                          we start a server-side job that rebuilds the
+                          index for the given repository.  Catalogs are not
+                          rebuilt by 'cmd=rebuild' queries, since this
+                          application only supports 'pkg/readonly' instances
+                          of svc:/application/pkg/depot.
+
+        PKG5_TEST_PROTO   If set, this points at the top of a proto area, used
+                          to ensure the WSGI application uses files from there
+                          rather than the test system.  This is only used when
+                          running the pkg5 test suite for depot_index.py
+        """
+
+        def __init__(self):
+                self.cache_dir = None
+                self.bgtask = None
+
+        def setup(self, request):
+                """Builds a dictionary of sr.Repository objects, keyed by the
+                repository prefix, and ensures our search indexes exist."""
+
+                def get_repo_paths():
+                        repo_paths = {}
+                        for key in request.wsgi_environ:
+                                if key.startswith("PKG5_REPOSITORY"):
+                                        prefix = key.replace("PKG5_REPOSITORY_",
+                                            "")
+                                        repo_paths[prefix] = \
+                                            request.wsgi_environ[key]
+                        return repo_paths
+
+                if repositories:
+                        return
+
+                # if running the pkg5 test suite, store the correct proto area
+                pkg5_test_proto = request.wsgi_environ.get("PKG5_TEST_PROTO",
+                    "")
+
+                repository_lock.acquire()
+                repo_paths = get_repo_paths()
+                self.cache_dir = request.wsgi_environ.get("PKG5_CACHE_DIR",
+                    "/var/cache/pkg/depot")
+
+                # We must ensure our BackgroundTask object has at least as many
+                # slots available as we have repositories, to allow the indexes
+                # to be refreshed. Ideally, we'd also account for a slot
+                # per-publisher, per-repository, but that might be overkill on a
+                # system with many repositories and many publishers that rarely
+                # get 'pkgrepo refresh' requests.
+                self.bgtask = BackgroundTask(len(repo_paths),
+                    busy_url="%s/depot/depot-keepalive" % request.base)
+                self.bgtask.start()
+
+                for prefix in repo_paths:
+                        path = repo_paths[prefix]
+                        repo_hash = hashlib.sha1(path).hexdigest()
+                        index_dir = os.path.sep.join(
+                            [self.cache_dir, "indexes", repo_hash])
+
+                        # if the index dir exists for this repository, we do not
+                        # automatically attempt a refresh.
+                        refresh_index = not os.path.exists(index_dir)
+                        repo = sr.Repository(root=path,
+                        read_only=True, writable_root=index_dir)
+
+                        repositories[prefix] = repo
+                        dconf = sd.DepotConfig()
+                        if refresh_index:
+                                self.bgtask.put(repo.refresh_index)
+
+                        depot = DepotBUI(repo, dconf, index_dir,
+                            pkg5_test_proto=pkg5_test_proto)
+                        depot_buis[prefix] = depot
+
+                repository_lock.release()
+
+        def get_accept_lang(self, request, depot_bui):
+                """Determine a language that this accept can request that we
+                also have templates for."""
+
+                rlangs = []
+                for entry in request.headers.elements("Accept-Language"):
+                        rlangs.append(str(entry).split(";")[0])
+                for rl in rlangs:
+                        if os.path.exists(os.path.join(depot_bui.web_root, rl)):
+                                return rl
+                return "en"
+
+        def repo_index(self, *tokens, **params):
+                """Generate a page showing the list of repositories served by
+                this Apache instance."""
+
+                self.setup(cherrypy.request)
+                # In order to reuse the pkg.depotd shtml files, we need to use
+                # the pkg.server.api, which means passing a DepotBUI object,
+                # despite the fact that we're not serving content for any one
+                # repository.  For the purposes of rendering this page, we'll
+                # use the first object we come across.
+                depot = depot_buis[depot_buis.keys()[0]]
+                accept_lang = self.get_accept_lang(cherrypy.request, depot)
+                cherrypy.request.path_info = "/%s" % accept_lang
+                tlookup = mako.lookup.TemplateLookup(
+                    directories=[depot.web_root,
+                    "%(web_root)s/%(lang)s/" % {"web_root": depot.web_root,
+                    "lang": accept_lang}])
+                pub = None
+                base = pkg.server.api.BaseInterface(cherrypy.request, depot,
+                    pub)
+
+                # build a list of all repositories URIs and BUI links,
+                # and a dictionary of publishers for each repository URI
+                repo_list = []
+                repo_pubs = {}
+                for repo_prefix in repositories.keys():
+                        repo = repositories[repo_prefix]
+                        depot = depot_buis[repo_prefix]
+                        repo_url = "%s/%s" % (cherrypy.request.base,
+                            repo_prefix)
+                        bui_link = "%s/%s/index.shtml" % \
+                            (repo_prefix, accept_lang)
+                        repo_list.append((repo_url, bui_link))
+                        repo_pubs[repo_url] = \
+			                [(pub, "%s/%s/%s" %
+                            (cherrypy.request.base, repo_prefix,
+                            pub)) for pub in repo.publishers]
+                repo_list.sort()
+                template = tlookup.get_template("repos.shtml")
+                return template.render_unicode(g_vars={"base": base,
+                    "pub": None, "http_depot": "true",
+		            "repo_list": repo_list, "repo_pubs": repo_pubs
+                    })
+
+        def default(self, *tokens, **params):
+                """ Our default handler is here to make sure we've called
+                setup, grabbing configuration from httpd.conf, then redirecting.
+                It also knows whether a request should be passed off to the
+                BUI, or whether we can just report an error."""
+
+                self.setup(cherrypy.request)
+
+                def request_pub_func(path):
+                        """Return the name of the publisher to be used
+                        for a given path. This function intentionally
+                        returns None for all paths."""
+                        return None
+
+                if "_themes" in tokens:
+                        # manipulate the path to remove everything up to _themes
+                        theme_index = tokens.index("_themes")
+                        cherrypy.request.path_info = "/".join(
+                            tokens[theme_index:])
+                        # When serving  theme resources we just choose the first
+                        # repository we find, which is fine since we're serving
+                        # content that's generic to all repositories, so we
+                        repo_prefix = repositories.keys()[0]
+                        repo = repositories[repo_prefix]
+                        depot_bui = depot_buis[repo_prefix]
+                        # use our custom request_pub_func, since theme resources
+                        # are not publisher-specific
+                        dh = sd.DepotHTTP(repo, depot_bui.cfg,
+                            request_pub_func=request_pub_func)
+                        return dh.default(*tokens[theme_index:])
+
+                elif tokens[0] not in repositories:
+                        raise cherrypy.NotFound()
+
+                # Otherwise, we'll try to serve the request from the BUI.
+
+                repo_prefix = tokens[0]
+                depot_bui = depot_buis[repo_prefix]
+                repo = repositories[repo_prefix]
+                # when serving reources, the publisher is not used
+                # to locate templates, so use our custom
+                # request_pub_func
+                dh = sd.DepotHTTP(repo, depot_bui.cfg,
+                    request_pub_func=request_pub_func)
+
+                # trim the repo_prefix
+                cherrypy.request.path_info = re.sub("^/%s" % repo_prefix, "",
+                    cherrypy.request.path_info)
+
+                accept_lang = self.get_accept_lang(cherrypy.request,
+                    depot_bui)
+                path = cherrypy.request.path_info.rstrip("/").lstrip("/")
+                toks = path.split("/")
+                pub = None
+
+                # look for a publisher in the path
+                if toks[0] in repo.publishers:
+                        path = "/".join(toks[1:])
+                        pub = toks[0]
+                        toks = self.__strip_pub(toks, repo)
+                        cherrypy.request.path_info = "/".join(toks)
+
+                # deal with users browsing directories
+                dirs = ["", accept_lang, repo_prefix]
+                if path in dirs:
+                        if not pub:
+                                raise cherrypy.HTTPRedirect(
+                                    "/%s/%s/index.shtml" %
+                                    (repo_prefix, accept_lang))
+                        else:
+                                raise cherrypy.HTTPRedirect(
+                                    "/%s/%s/%s/index.shtml" %
+                                    (repo_prefix, pub, accept_lang))
+
+                resp = face.respond(depot_bui, cherrypy.request,
+                    cherrypy.response, pub, http_depot=repo_prefix)
+                return resp
+
+        def manifest(self, *tokens):
+                """Manifest requests coming from the BUI need to be redirected
+                back through the RewriteRules defined in the Apache
+                configuration in order to be served directly.
+                pkg(1) will never hit this code, as those requests don't get
+                handled by this webapp.
+                """
+
+                self.setup(cherrypy.request)
+                rel_uri = cherrypy.request.path_info
+
+                # we need to recover the escaped portions of the URI
+                redir = rel_uri.lstrip("/").split("/")
+                pub_mf = "/".join(redir[0:4])
+                pkg_name = "/".join(redir[4:])
+                # encode the URI so our RewriteRules can process them
+                pkg_name = urllib.quote(pkg_name)
+                pkg_name = pkg_name.replace("/", "%2F")
+                pkg_name = pkg_name.replace("%40", "@", 1)
+
+                # build a URI that we can redirect to
+                redir = "%s/%s" % (pub_mf, pkg_name)
+                redir = "/%s" % redir.lstrip("/")
+                raise cherrypy.HTTPRedirect(redir)
+
+        def __build_depot_http(self):
+                """Build a DepotHTTP object to handle the current request."""
+                self.setup(cherrypy.request)
+                headers = cherrypy.response.headers
+                headers["Content-Type"] = "text/plain; charset=utf-8"
+
+                toks = cherrypy.request.path_info.lstrip("/").split("/")
+                repo_prefix = toks[0]
+                if repo_prefix not in repositories:
+                        raise cherrypy.NotFound()
+
+                repo = repositories[repo_prefix]
+                depot_bui = depot_buis[repo_prefix]
+                def request_pub_func(path_info):
+                        """A function that can be called to determine the
+                        publisher for a given request. We always want None
+                        here, to force DepotHTTP to fallback to the publisher
+                        information in the FMRI provided as part of the request,
+                        rather than the /publisher/ portion of path_info.
+                        """
+                        return None
+
+                return sd.DepotHTTP(repo, depot_bui.cfg,
+                    request_pub_func=request_pub_func)
+
+        def __strip_pub(self, tokens, repo):
+                """Attempt to strip at most one publisher from the path
+                described by 'tokens' looking for the publishers configured
+                in 'repo', returning new tokens."""
+
+                if len(tokens) <= 0:
+                        return tokens
+                stripped = False
+                # For our purposes, the first token is always the repo_prefix
+                # indicating which repository we're talking to.
+                new_tokens = [tokens[0]]
+                for t in tokens[1:]:
+                        if t in repo.publishers and not stripped:
+                                stripped = True
+                                pass
+                        else:
+                                new_tokens.append(t)
+                return new_tokens
+
+        def info(self, *tokens):
+                """Use a DepotHTTP to return an info response."""
+
+                dh = self.__build_depot_http()
+                tokens = self.__strip_pub(tokens, dh.repo)
+                return dh.info_0(*tokens[3:])
+
+        def p5i(self, *tokens):
+                """Use a into DepotHTTP to return a p5i response."""
+
+                dh = self.__build_depot_http()
+                tokens = self.__strip_pub(tokens, dh.repo)
+                headers = cherrypy.response.headers
+                headers["Content-Type"] = pkg.p5i.MIME_TYPE
+                return dh.p5i_0(*tokens[3:])
+
+        def search_1(self, *tokens, **params):
+                """Use a DepotHTTP to return a search/1 response."""
+
+                toks = cherrypy.request.path_info.lstrip("/").split("/")
+                dh = self.__build_depot_http()
+                toks = self.__strip_pub(tokens, dh.repo)
+                query_str = "/".join(toks[3:])
+                return dh.search_1(query_str)
+
+        def search_0(self, *tokens):
+                """Use a DepotHTTP to return a search/0 response."""
+
+                toks = cherrypy.request.path_info.lstrip("/").split("/")
+                dh = self.__build_depot_http()
+                toks = self.__strip_pub(tokens, dh.repo)
+                return dh.search_0(toks[-1])
+
+        def admin(self, *tokens, **params):
+                """ We support limited admin/0 operations.  For a repository
+                refresh, we only honor the index rebuild itself.
+
+                Since a given http-depot server may be serving many repositories
+                we expend a little more effort than pkg.server.depot when
+                accepting refresh requests when our existing BackgroundTask
+                Queue is full, retrying jobs for up to a minute.  In the future,
+                we may want to make the Queue scale according to the size of the
+                depot/repository.
+                """
+                self.setup(cherrypy.request)
+                request = cherrypy.request
+                cmd = params.get("cmd")
+                if not cmd:
+                        return
+                if cmd not in ["refresh", "refresh-indexes"]:
+                        raise AdminOpNotSupportedException(
+                            request.wsgi_environ["REQUEST_URI"], cmd)
+
+                # Determine whether to allow index rebuilds
+                if request.wsgi_environ.get(
+                    "PKG5_ALLOW_REFRESH", "false").lower() != "true":
+                        raise AdminOpsDisabledException(
+                            request.wsgi_environ["REQUEST_URI"])
+
+                repository_lock.acquire()
+                try:
+                        if len(tokens) <= 2:
+                                raise cherrypy.NotFound()
+                        repo_prefix = tokens[0]
+                        pub_prefix = tokens[1]
+
+                        if repo_prefix not in repositories:
+                                raise cherrypy.NotFound()
+
+                        repo = repositories[repo_prefix]
+                        if pub_prefix not in repo.publishers:
+                                raise cherrypy.NotFound()
+
+                        # we need to reload the repository in order to get
+                        # any new catalog contents before refreshing the
+                        # index.
+                        repo.reload()
+                        try:
+                                self.bgtask.put(repo.refresh_index,
+                                    pub=pub_prefix)
+                        except Queue.Full, e:
+                                retries = 10
+                                success = False
+                                while retries > 0 and not success:
+                                        time.sleep(5)
+                                        try:
+                                                self.bgtask.put(
+                                                    repo.refresh_index,
+                                                    pub=pub_prefix)
+                                                success = True
+                                        except Exception, ex:
+                                                pass
+                                if not success:
+                                        raise cherrypy.HTTPError(
+                                            status=httplib.SERVICE_UNAVAILABLE,
+                                            message="Unable to refresh the "
+                                            "index for %s after repeated "
+                                            "retries. Try again later." %
+                                            request.path_info)
+                finally:
+                        repository_lock.release()
+                return ""
+
+        def wait_refresh(self, *tokens, **params):
+                """Not a pkg(5) operation, this allows clients to wait until any
+                pending index refresh operations have completed.
+
+                This method exists primarily for the pkg(5) test suite to ensure
+                that we do not attempt to perform searches when the server is
+                still coming up.
+                """
+                self.setup(cherrypy.request)
+                self.bgtask.join()
+                return ""
+
+
+class Pkg5Dispatch(object):
+        """A custom CherryPy dispatcher used by our application.
+        We use this, because the default dispatcher in CherryPy seems to dislike
+        trying to have an exposed "default" method (the special method name used
+        by CherryPy in its default dispatcher to handle unmapped resources) as
+        well as trying to serve resources named "default", a common name for
+        svc:/application/pkg/server SMF instances, which become the names of the
+        repo_prefixes used by the http-depot.
+        """
+
+        def __init__(self, wsgi_depot):
+                self.app = wsgi_depot
+                # needed to convince CherryPy that we are a valid dispatcher
+                self.config = {}
+
+        @staticmethod
+        def default_error_page(status=httplib.NOT_FOUND, message="oops",
+            traceback=None, version=None):
+                """This function is registered as the default error page
+                for CherryPy errors.  This sets the response headers to
+                be uncacheable, and then returns a HTTP response."""
+
+                response = cherrypy.response
+                for key in ('Cache-Control', 'Pragma'):
+                        if key in response.headers:
+                                del response.headers[key]
+
+                # Server errors are interesting, so let's log them.  In the case
+                # of an internal server error, we send a 404 to the client. but
+                # log the full details in the server log.
+                if (status == httplib.INTERNAL_SERVER_ERROR or
+                    status.startswith("500 ")):
+                        # Convert the error to a 404 to obscure implementation
+                        # from the client, but log the original error to the
+                        # server logs.
+                        error = cherrypy._cperror._HTTPErrorTemplate % \
+                            {"status": httplib.NOT_FOUND,
+                            "message": httplib.responses[httplib.NOT_FOUND],
+                            "traceback": "",
+                            "version": cherrypy.__version__}
+                        print "Path that raised exception was %s" % \
+                            cherrypy.request.path_info
+                        print message
+                        return error
+                else:
+                        error = cherrypy._cperror._HTTPErrorTemplate % \
+                            {"status": httplib.NOT_FOUND, "message": message,
+                            "traceback": "", "version": cherrypy.__version__}
+                        return error
+
+        def dispatch(self, path_info):
+                request = cherrypy.request
+                request.config = {}
+                request.error_page["default"] = Pkg5Dispatch.default_error_page
+
+                toks = path_info.lstrip("/").split("/")
+                params = request.params
+                file_type = toks[-1].split(".")[-1]
+
+                try:
+                        if "/search/1/" in path_info:
+                                cherrypy.response.stream = True
+                                cherrypy.response.body = self.app.search_1(
+                                    *toks, **params)
+                        elif "/search/0/" in path_info:
+                                cherrypy.response.stream = True
+                                cherrypy.response.body = self.app.search_0(
+                                    *toks)
+                        elif "/manifest/0/" in path_info:
+                                cherrypy.response.body = self.app.manifest(
+                                    *toks)
+                        elif "/info/0/" in path_info:
+                                cherrypy.response.body = self.app.info(*toks,
+                                    **params)
+                        elif "/p5i/0/" in path_info:
+                                cherrypy.response.body = self.app.p5i(*toks,
+                                    **params)
+                        elif "/admin/0" in path_info:
+                                cherrypy.response.body = self.app.admin(*toks,
+                                    **params)
+                        elif "/depot-keepalive" in path_info:
+                                return ""
+                        elif "/depot-wait-refresh" in path_info:
+                                self.app.wait_refresh(*toks, **params)
+                                return ""
+                        elif path_info == "/" or path_info == "/repos.shtml":
+                                cherrypy.response.body = self.app.repo_index(
+                                    *toks, **params)
+                        elif file_type in ["css", "shtml", "png"]:
+                                cherrypy.response.body = self.app.default(*toks,
+                                    **params)
+                        else:
+                                cherrypy.response.body = self.app.default(*toks,
+                                    **params)
+                except Exception, e:
+                        if isinstance(e, cherrypy.HTTPRedirect):
+                                raise
+                        elif isinstance(e, cherrypy.HTTPError):
+                                raise
+                        elif isinstance(e, AdminOpsDisabledException):
+                                raise cherrypy.HTTPError(e.http_status,
+                                    "This operation has been disabled by the "
+                                    "server administrator.")
+                        elif isinstance(e, AdminOpNotSupportedException):
+                                raise cherrypy.HTTPError(e.http_status,
+                                    "This operation is not supported.")
+                        else:
+                                # we leave this as a 500 for now. It will be
+                                # converted and logged by our error handler
+                                # before the client sees it.
+                                raise cherrypy.HTTPError(
+                                    status=httplib.INTERNAL_SERVER_ERROR,
+                                    message="".join(traceback.format_exc(e)))
+
+wsgi_depot = WsgiDepot()
+dispatcher = Pkg5Dispatch(wsgi_depot)
+
+conf = {"/":
+    {'request.dispatch': dispatcher.dispatch}}
+application = cherrypy.Application(wsgi_depot, None, config=conf)
+# Raise the level of the access log to make it quiet. For some reason,
+# setting log.access_file = "" or None doesn't work.
+application.log.access_log.setLevel(logging.WARNING)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/apache2/depot/repos.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,69 @@
+## -*- coding: utf-8 -*-
+##
+## CDDL HEADER START
+##
+## The contents of this file are subject to the terms of the
+## Common Development and Distribution License (the "License").
+## You may not use this file except in compliance with the License.
+##
+## You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+## or http://www.opensolaris.org/os/licensing.
+## See the License for the specific language governing permissions
+## and limitations under the License.
+##
+## When distributing Covered Code, include this CDDL HEADER in each
+## file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+## If applicable, add the following below this CDDL HEADER, with the
+## fields enclosed by brackets "[]" replaced with your own identifying
+## information: Portions Copyright [yyyy] [name of copyright owner]
+##
+## CDDL HEADER END
+##
+## Copyright 2013 Oracle and/or its affiliates. All rights reserved.
+##
+<%page args="g_vars, gmenu_items=None"/>\
+<%def name="page_crumbs(g_vars)"><%
+        # None at top level.
+        return []
+%></%def>\
+<%def name="global_menu_items(g_vars)"><%
+        # Just this list of repositories.
+        return [("/", "Repositories")]
+%></%def>\
+<%inherit file="layout.shtml"/>\
+<%
+        repo_list = g_vars["repo_list"]
+        repo_pubs = g_vars["repo_pubs"]
+%>
+<%def name="document_class()"><%
+        return "yui-t4"
+%></%def>\
+<div id="custom-doc" class="${self.document_class()}">
+        <div id="hd">
+<div id="yui-main">
+        <div>
+        <h2 class="section-title">IPS Repositories</h2>
+        <p align="left">The following package repositories are available from this server:
+        <div class="results">
+        <table summary="A list of the package repositories available from this server.">
+            <tr class="first">
+                <th scope="row">URI</th><th scope="row">Publishers</th>
+                </tr>
+% for repo_uri, bui_link in repo_list:
+                <tr><td align="left"><a href="${bui_link}">${repo_uri}</a></td>
+		        <td>
+%         for pub, uri in repo_pubs[repo_uri]:
+		        <a href="${uri}">${pub}</a> 
+%         endfor pub
+                </td>
+		        </tr>
+% endfor repo_uri
+                </table>
+        </div>
+        </div>
+</div>
+
+
+<%def name="page_title(g_vars)"><%
+        return "ips repository server"
+%></%def>\
--- a/src/util/apache2/sysrepo/sysrepo_httpd.conf.mako	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/apache2/sysrepo/sysrepo_httpd.conf.mako	Wed Aug 14 11:12:35 2013 +0530
@@ -58,9 +58,9 @@
 LoadModule dir_module libexec/64/mod_dir.so
 LoadModule alias_module libexec/64/mod_alias.so
 LoadModule rewrite_module libexec/64/mod_rewrite.so
-
 LoadModule env_module libexec/64/mod_env.so
 LoadModule wsgi_module libexec/64/mod_wsgi-2.6.so
+
 # We only alias a specific script, not all files in ${sysrepo_template_dir}
 WSGIScriptAlias /wsgi_p5p ${sysrepo_template_dir}/sysrepo_p5p.py
 WSGIDaemonProcess sysrepo processes=1 threads=21 user=pkg5srv group=pkg5srv display-name=pkg5_sysrepo inactivity-timeout=120
@@ -382,9 +382,9 @@
                         # File and p5p-based repositories get our static
                         # versions and publisher responses
                         context.write("RewriteRule ^/%(pub)s/%(hash)s/versions/0 "
-                            "/versions/0/index.html [L,NE]\n" % locals())
+                            "%%{DOCUMENT_ROOT}/versions/0/index.html [L,NE]\n" % locals())
                         context.write("RewriteRule ^/%(pub)s/%(hash)s/publisher/0 "
-                            "/%(pub)s/%(hash)s/publisher/0/index.html [L,NE]\n" % locals())
+                            "%%{DOCUMENT_ROOT}/%(pub)s/%(hash)s/publisher/0/index.html [L,NE]\n" % locals())
                         # A p5p archive repository
                         if utype == "file":
                                 repo_path = "/%s" % uri.replace("file:", "").lstrip("/")
@@ -445,7 +445,7 @@
                             "/%(pub)s/%(hash)s/manifest/0/([^@]+)@([^\ ]+)(\ HTTP/1.1)$ "
                             "/%(pub)s/%(hash)s/publisher/%(pub)s/pkg/$1/$2 [NE,PT,C]\n"
                             % locals())
-                        context.write("RewriteRule ^/%(pub)s/%(hash)s/(.*)$ - [NE,L]"
+                        context.write("RewriteRule ^/%(pub)s/%(hash)s/(.*)$ %%{DOCUMENT_ROOT}/%(pub)s/%(hash)s/$1 [NE,L]"
                             % locals())
 %>
                 % else:
@@ -493,9 +493,9 @@
         % endif
 % endfor uri
 
-# any non-file-based repositories get our local versions and syspub responses
-RewriteRule ^.*/versions/0/?$ - [L]
-RewriteRule ^.*/syspub/0/?$ - [L]
+# any repositories get our local versions and syspub responses
+RewriteRule ^.*/versions/0/?$ %{DOCUMENT_ROOT}/versions/0/index.html [L]
+RewriteRule ^.*/syspub/0/?$ %{DOCUMENT_ROOT}/syspub/0/index.html [L]
 # allow for 'OPTIONS * HTTP/1.0' requests
 RewriteCond %{REQUEST_METHOD} OPTIONS [NC]
 RewriteRule \* - [L]
--- a/src/util/misc/auth_attr.d/package:pkg	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/misc/auth_attr.d/package:pkg	Wed Aug 14 11:12:35 2013 +0530
@@ -1,3 +1,5 @@
 solaris.smf.read.pkg-server:::Read permissions for protected pkg(5) Server Service Properties::
 solaris.smf.value.pkg-sysrepo:::Change pkg(5) System Repository Service values::
 solaris.smf.manage.pkg-sysrepo:::Manage pkg(5) System Repository Service states::
+solaris.smf.manage.pkg-mirror:::Manage pkg(5) Mirror Service states::
+solaris.smf.value.pkg-mirror:::Change pkg(5) Mirror Service values::
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/misc/user_attr.d/package:pkg	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,1 @@
+pkg5srv::RO::auths=solaris.smf.manage.pkg-mirror,solaris.smf.value.pkg-mirror
--- a/src/util/publish/pkgdiff.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/publish/pkgdiff.py	Wed Aug 14 11:12:35 2013 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import getopt
@@ -47,11 +47,12 @@
 
         print _("""\
 Usage:
-        pkgdiff [-i attribute ...] [-o attribute] [-v variant=value ...]
-            file1 file2""")
+        pkgdiff [-i attribute]... [-o attribute]
+            [-t action_name[,action_name]...]...
+            [-v name=value]... (file1 | -) (file2 | -)""")
         sys.exit(exitcode)
 
-def error(text, exitcode=1):
+def error(text, exitcode=3):
         """Emit an error message prefixed by the command name """
 
         print >> sys.stderr, "pkgdiff: %s" % text
@@ -65,30 +66,36 @@
 
         ignoreattrs = []
         onlyattrs = []
+        onlytypes = []
         varattrs = defaultdict(set)
 
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "i:o:v:", ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "i:o:t:v:?", ["help"])
                 for opt, arg in opts:
                         if opt == "-i":
                                 ignoreattrs.append(arg)
-                        if opt == "-o":
+                        elif opt == "-o":
                                 onlyattrs.append(arg)
-                        if opt == "-v":
+                        elif opt == "-t":
+                                onlytypes.extend(arg.split(","))
+                        elif opt == "-v":
                                 args = arg.split("=")
                                 if len(args) != 2:
                                         usage(_("variant option incorrect %s") % arg)
                                 if not args[0].startswith("variant."):
                                         args[0] = "variant." + args[0]
                                 varattrs[args[0]].add(args[1])
-                        if opt in ("--help", "-?"):
+                        elif opt in ("--help", "-?"):
                                 usage(exitcode=0)
 
         except getopt.GetoptError, e:
                 usage(_("illegal global option -- %s") % e.opt)
 
         if len(pargs) != 2:
-                usage(_("two file arguments are required."))
+                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."))
@@ -100,21 +107,47 @@
 
         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: %s" %
+                    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)):
-                        m.set_content(pathname=p)
+                        if p == "-":
+                                m.set_content(content=sys.stdin.read())
+                        else:
+                                m.set_content(pathname=p)
         except (pkg.actions.ActionError, apx.InvalidPackageErrors), e:
                 error(_("Action error in file %(p)s: %(e)s") % locals())
         except (EnvironmentError, apx.ApiException), 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()
-
-        # implement manifest filtering
         for vname in varattrs:
                 for path, v, m in zip(pargs, (v1, v2), (manifest1, manifest2)):
                         if vname not in v:
@@ -133,6 +166,7 @@
                             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()
@@ -144,7 +178,8 @@
         # 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 %s %s") % (v1, v2))
+                        error(_("Manifests support different variants "
+                            "%(v1)s %(v2)s") % {"v1": v1, "v2": v2})
 
         # Now, get a list of all possible variant values, including None
         # across all variants and both manifests
@@ -181,8 +216,8 @@
                 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
@@ -239,7 +274,7 @@
                         out = k + "=" + v
                 return out
 
-        #figure out when to print diffs
+        # figure out when to print diffs
         def conditional_print(s, a):
                 if onlyattrs:
                         if not set(a.attrs.keys()) & onlyattrs:
--- a/src/util/publish/pkglint.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/publish/pkglint.py	Wed Aug 14 11:12:35 2013 +0530
@@ -239,13 +239,15 @@
                         f = codecs.open(filename, "rb", "utf-8")
                         data = f.read()
                 except UnicodeDecodeError, e:
-                        lint_logger.critical(_("Invalid file %s: "
-                            "manifest not encoded in UTF-8: %s") %
-                            (filename, e), msgid="lint.manifest002")
+                        lint_logger.critical(_("Invalid file %(file)s: "
+                            "manifest not encoded in UTF-8: %(err)s") %
+                            {"file": filename, "err": e},
+                            msgid="lint.manifest002")
                         continue
                 except IOError, e:
                         lint_logger.critical(_("Unable to read manifest file "
-                        "%s: %s") % (filename, e), msgid="lint.manifest001")
+                            "%(file)s: %(err)s") % {"file": filename, "err": e},
+                            msgid="lint.manifest001")
                         continue
                 lines.append(data)
                 linecnt = len(data.splitlines())
--- a/src/util/publish/pkgmerge.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/publish/pkgmerge.py	Wed Aug 14 11:12:35 2013 +0530
@@ -52,6 +52,16 @@
         import sys
         sys.exit(1)
 
+class PkgmergeException(Exception):
+        """An exception raised if something goes wrong during the merging
+        process."""
+
+        def __unicode__(self):
+                # To workaround python issues 6108 and 2517, this provides a
+                # a standard wrapper for this class' exceptions so that they
+                # have a chance of being stringified correctly.
+                return str(self)
+
 BUILD_RELEASE  = "5.11"  # Should be an option to this program some day?
 
 catalog_dict   = {}    # hash table of catalogs by source uri
@@ -95,7 +105,7 @@
         msg(_("""\
 Usage:
         pkgmerge [-n] -d dest_repo -s variant=value[,...],src_repo ...
-            [pkg_fmri_pattern ...]
+            [-p publisher_prefix ... ] [pkg_fmri_pattern ...]
 
 Options:
         -d dest_repo
@@ -115,6 +125,12 @@
                 be named for all sources.  This option may be specified multiple
                 times.
 
+        -p publisher_prefix
+                The name of the publisher we should merge packages from.  This
+                option may be specified multiple times.  If no -p option is
+                used, the default is to merge packages from all publishers in
+                all source repositories.
+
         --help or -?
                 Displays a usage message.
 
@@ -134,15 +150,12 @@
         if exitcode != None:
                 sys.exit(exitcode)
 
-def get_tracker(quiet=False):
-        if quiet:
-                progresstracker = progress.QuietProgressTracker()
-        else:
-                try:
-                        progresstracker = \
-                            progress.FancyUNIXProgressTracker()
-                except progress.ProgressTrackerException:
-                        progresstracker = progress.CommandLineProgressTracker()
+def get_tracker():
+        try:
+                progresstracker = \
+                    progress.FancyUNIXProgressTracker()
+        except progress.ProgressTrackerException:
+                progresstracker = progress.CommandLineProgressTracker()
         return progresstracker
 
 def load_catalog(repouri, pub):
@@ -187,9 +200,12 @@
         dest_repo     = None
         source_list   = []
         variant_list  = []
+        pub_list      = []
+        use_pub_list  = False
 
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "d:ns:?", ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "d:np:s:?",
+                    ["help"])
                 for opt, arg in opts:
                         if opt == "-d":
                                 dest_repo = misc.parse_uri(arg)
@@ -217,6 +233,9 @@
                                 variant_list.append(src_vars)
                                 source_list.append(publisher.RepositoryURI(
                                     misc.parse_uri(s[-1])))
+                        elif opt == "-p":
+                                use_pub_list = True
+                                pub_list.append(arg)
 
                         if opt in ("--help", "-?"):
                                 usage(exitcode=0)
@@ -282,82 +301,187 @@
         xport, xport_cfg = transport.setup_transport()
         xport_cfg.incoming_root = tmpdir
 
-        pub = transport.setup_publisher(source_list,
+        # we don't use the publisher returned by setup_publisher, as that only
+        # returns one of the publishers in source_list.  Instead we use
+        # xport_cfg to access all publishers.
+        transport.setup_publisher(source_list,
             "pkgmerge", xport, xport_cfg, remote_prefix=True)
         cat_dir = tempfile.mkdtemp(dir=tmpdir)
-        pub.meta_root = cat_dir
-        pub.transport = xport
+
+        # we must have at least one matching publisher if -p was used.
+        known_pubs = set([pub.prefix for pub in xport_cfg.gen_publishers()])
+        if pub_list and len(set(pub_list).intersection(known_pubs)) == 0:
+                error(_("no publishers from source repositories match "
+                    "the given -p options."))
+
+        errors = set()
+        tracker = get_tracker()
 
-        # Use separate transport for destination repository in case source
-        # and destination have identical publisher configuration.
-        dest_xport, dest_xport_cfg = transport.setup_transport()
-        dest_xport_cfg.incoming_root = tmpdir
+        # iterate over all publishers in our source repositories.  If errors
+        # are encountered for a given publisher, we accumulate those, and
+        # skip to the next publisher.
+        for pub in xport_cfg.gen_publishers():
 
-        # retrieve catalogs for all specified repositories
-        for s in source_list:
-                load_catalog(s, pub)
+                if use_pub_list:
+                        if pub.prefix not in pub_list:
+                                continue
+                        else:
+                                # remove publishers from pub_list as we go, so
+                                # that when we're finished, any remaining
+                                # publishers in pub_list suggest superfluous
+                                # -p options, which will cause us to exit with
+                                # an error.
+                                pub_list.remove(pub.prefix)
+
+                pub.meta_root = cat_dir
+                pub.transport = xport
 
-        # determine the list of packages we'll be processing
-        if not pargs:
-                # use the latest versions and merge everything
-                fmri_arguments = list(set(
-                    name
+                # Use separate transport for destination repository in case
+                # source and destination have identical publisher configuration.
+                dest_xport, dest_xport_cfg = transport.setup_transport()
+                dest_xport_cfg.incoming_root = tmpdir
+
+                # retrieve catalogs for all specified repositories
+                for s in source_list:
+                        load_catalog(s, pub)
+
+                # determine the list of packages we'll be processing
+                if not pargs:
+                        # use the latest versions and merge everything
+                        fmri_arguments = list(set(
+                            name
+                            for s in source_list
+                            for name in get_all_pkg_names(s)
+                        ))
+                        exclude_args = []
+                else:
+                        fmri_arguments = [
+                            f
+                            for f in pargs
+                            if not f.startswith("!")
+                        ]
+
+                        exclude_args = [
+                            f[1:]
+                            for f in pargs
+                            if f.startswith("!")
+                        ]
+
+                # build fmris to be merged
+                masterlist = [
+                    build_merge_list(fmri_arguments, exclude_args,
+                        catalog_dict[s.uri])
                     for s in source_list
-                    for name in get_all_pkg_names(s)
-                ))
-                exclude_args = []
-        else:
-                fmri_arguments = [
-                    f
-                    for f in pargs
-                    if not f.startswith("!")
-                ]
-
-                exclude_args = [
-                    f[1:]
-                    for f in pargs
-                    if f.startswith("!")
                 ]
 
-        # build fmris to be merged
-        masterlist = [
-            build_merge_list(fmri_arguments, exclude_args, catalog_dict[s.uri])
-            for s in source_list
-        ]
+                # check for unmatched patterns
+                in_none = reduce(lambda x, y: x & y,
+                    (set(u) for d, u in masterlist))
+                if in_none:
+                        errors.add(
+                            _("The following pattern(s) did not match any "
+                            "packages in any of the specified repositories for "
+                            "publisher %(pub_name)s:"
+                            "\n%(patterns)s") % {"patterns": "\n".join(in_none),
+                            "pub_name": pub.prefix})
+                        continue
+
+                # generate set of all package names to be processed, and dict
+                # of lists indexed by order in source_list; if that repo has no
+                # fmri for this pkg then use None.
+                allpkgs = set(name for d, u in masterlist for name in d)
+
+                processdict = {}
+                for p in allpkgs:
+                        for d, u in masterlist:
+                                processdict.setdefault(p, []).append(
+                                    d.setdefault(p, None))
 
-        # check for unmatched patterns
-        in_none = reduce(lambda x, y: x & y, (set(u) for d, u in masterlist))
-        if in_none:
-                error(_("The following pattern(s) did not match any packages "
-                    "in any of the specified repositories:\n%s") % "\n".join(
-                    in_none))
+                # check to make sure all fmris are at same version modulo
+                # timestamp
+                for entry in processdict:
+                        if len(set([
+                                str(a).rsplit(":")[0]
+                                for a in processdict[entry]
+                                if a is not None
+                            ])) > 1:
+                                errors.add(
+                                    _("fmris matching the following patterns do"
+                                    " not have matching versions across all "
+                                    "repositories for publisher %(pubs)s: "
+                                    "%(patterns)s") % {"pub": pub.prefix,
+                                    "patterns": processdict[entry]})
+                                continue
 
-        # generate set of all package names to be processed, and dict of lists
-        # indexed by order in source_list; if that repo has no fmri for this
-        # pkg then use None.
-        allpkgs = set(name for d, u in masterlist for name in d)
+                # we're ready to merge
+                if not dry_run:
+                        target_pub = transport.setup_publisher(dest_repo,
+                            pub.prefix, dest_xport, dest_xport_cfg,
+                            remote_prefix=True)
+                else:
+                        target_pub = None
 
-        processdict = {}
-        for p in allpkgs:
-                for d, u in masterlist:
-                        processdict.setdefault(p, []).append(d.setdefault(p,
-                            None))
+                tracker.republish_set_goal(len(processdict), 0, 0)
+                # republish packages for this publisher. If we encounter any
+                # publication errors, we move on to the next publisher.
+                try:
+                        pkg_tmpdir = tempfile.mkdtemp(dir=tmpdir)
+                        republish_packages(pub, target_pub,
+                            processdict, source_list, variant_list, variants,
+                            tracker, xport, dest_repo, dest_xport, pkg_tmpdir,
+                            dry_run=dry_run)
+                except (trans.TransactionError, PkgmergeException), e:
+                        errors.add(str(e))
+                        tracker.reset()
+                        continue
+                finally:
+                        # if we're handling an exception, this still gets called
+                        # in spite of the 'continue' that the handler ends with.
+                        if os.path.exists(pkg_tmpdir):
+                                shutil.rmtree(pkg_tmpdir)
+
+                tracker.republish_done(dryrun=dry_run)
+                tracker.reset()
+
+        # If -p options were supplied, we should have processed all of them
+        # by now. Remaining entries suggest -p options that were not merged.
+        if use_pub_list and pub_list:
+                errors.add(_("the following publishers were not found in "
+                    "source repositories: %s") % " ".join(pub_list))
 
-        # check to make sure all fmris are at same version modulo timestamp
-        for entry in processdict:
-                if len(set([
-                        str(a).rsplit(":")[0]
-                        for a in processdict[entry]
-                        if a is not None
-                    ])) > 1:
-                        error(_("fmris matching the following patterns do not "
-                            "have matching versions across all repositories: "
-                            "%s") % processdict[entry])
+        # If we have encountered errors for some publishers, print them now
+        # and exit.
+        tracker.flush()
+        for message in errors:
+                error(message, exitcode=None)
+        if errors:
+                exit(1)
+
+        return 0
+
+def republish_packages(pub, target_pub, processdict, source_list, variant_list,
+        variants, tracker, xport, dest_repo, dest_xport, pkg_tmpdir,
+        dry_run=False):
+        """Republish packages for publisher pub to dest_repo.
 
-        # we're ready to merge
-        if not dry_run:
-                target_pub = transport.setup_publisher(dest_repo,
-                    pub.prefix, dest_xport, dest_xport_cfg, remote_prefix=True)
+        If we try to republish a package that we have already published,
+        an exception is raise.
+
+        pub             the publisher from source_list that we are republishing
+        target_pub      the destination publisher
+        processdict     a dict indexed by package name of the pkgs to merge
+        source_list     a list of source respositories
+        variant_list    a list of dicts containing variant names/values
+        variants        the unique set of variants across all sources.
+        tracker         a progress tracker
+        xport           the transport handling our source repositories
+        dest_repo       our destination repository
+        dest_xport      the transport handling our destination repository
+        pkg_tmpdir      a temporary dir used when downloading pkg content
+                        which may be deleted and recreated by this method.
+
+        dry_run         True if we should not actually publish
+        """
 
         def get_basename(pfmri):
                 open_time = pfmri.get_timestamp()
@@ -365,8 +489,6 @@
                     (calendar.timegm(open_time.utctimetuple()),
                     urllib.quote(str(pfmri), ""))
 
-        tracker = get_tracker()
-        tracker.republish_set_goal(len(processdict), 0, 0)
         for entry in processdict:
                 man, retrievals = merge_fmris(source_list,
                     processdict[entry], variant_list, variants)
@@ -392,70 +514,66 @@
 
                 tracker.republish_start_pkg(f, getbytes=getbytes,
                     sendbytes=sendbytes)
+
                 if dry_run:
                         # Dry-run; attempt a merge of everything but don't
                         # write any data or publish packages.
                         continue
 
-                pkgdir = tempfile.mkdtemp(dir=tmpdir)
+                target_pub.prefix = f.publisher
+
                 # Retrieve package data from each package source.
                 for i, uri in enumerate(source_list):
                         pub.repository.origins = [uri]
-                        mfile = xport.multi_file_ni(pub, pkgdir,
+                        mfile = xport.multi_file_ni(pub, pkg_tmpdir,
                             decompress=True, progtrack=tracker)
                         for a in retrievals[i]:
                                 mfile.add_action(a)
                         mfile.wait_files()
 
+                trans_id = get_basename(f)
+                pkg_name = f.get_fmri()
+                pubs.add(target_pub.prefix)
                 # Publish merged package.
-                try:
-                        trans_id = get_basename(f)
-                        pkg_name = f.get_fmri()
-                        target_pub.prefix = f.publisher
-                        pubs.add(f.publisher)
+                t = trans.Transaction(dest_repo,
+                    pkg_name=pkg_name, trans_id=trans_id,
+                    xport=dest_xport, pub=target_pub,
+                    progtrack=tracker)
 
-                        t = trans.Transaction(dest_repo, pkg_name=pkg_name,
-                            trans_id=trans_id, xport=dest_xport, pub=target_pub,
-                            progtrack=tracker)
-
-                        # Remove any previous failed attempt to
-                        # to republish this package.
-                        try:
-                                t.close(abandon=True)
-                        except:
-                                # It might not exist already.
-                                pass
+                # Remove any previous failed attempt to
+                # to republish this package.
+                try:
+                        t.close(abandon=True)
+                except:
+                        # It might not exist already.
+                        pass
 
-                        t.open()
-                        for a in man.gen_actions():
-                                if (a.name == "set" and
-                                    a.attrs["name"] == "pkg.fmri"):
-                                        # To be consistent with the
-                                        # server, the fmri can't be
-                                        # added to the manifest.
-                                        continue
+                t.open()
+                for a in man.gen_actions():
+                        if (a.name == "set" and
+                            a.attrs["name"] == "pkg.fmri"):
+                                # To be consistent with the
+                                # server, the fmri can't be
+                                # added to the manifest.
+                                continue
 
-                                if hasattr(a, "hash"):
-                                        fname = os.path.join(pkgdir,
-                                            a.hash)
-                                        a.data = lambda: open(fname, "rb")
-                                t.add(a)
+                        if hasattr(a, "hash"):
+                                fname = os.path.join(pkg_tmpdir,
+                                    a.hash)
+                                a.data = lambda: open(
+                                    fname, "rb")
+                        t.add(a)
 
-                        # Always defer catalog update.
-                        t.close(add_to_catalog=False)
-                except trans.TransactionError, e:
-                        error(str(e))
+                # Always defer catalog update.
+                t.close(add_to_catalog=False)
 
                 # Done with this package.
                 tracker.republish_end_pkg(f)
 
-                # Dump retrieved package data after each republication.
-                shutil.rmtree(pkgdir)
-
-        tracker.republish_done(dryrun=dry_run)
-        tracker.reset()
-
-        return 0
+                # Dump retrieved package data after each republication and
+                # recreate the directory for the next package.
+                shutil.rmtree(pkg_tmpdir)
+                os.mkdir(pkg_tmpdir)
 
 def merge_fmris(source_list, fmri_list, variant_list, variants):
         """Merge a list of manifests representing multiple variants,
@@ -637,7 +755,8 @@
 
                         if a.name == "set" and a.attrs["name"] == variant:
                                 if vval not in a.attrlist("value"):
-                                        error(_("package %(pkg)s is tagged as "
+                                        raise PkgmergeException(
+                                            _("package %(pkg)s is tagged as "
                                             "not supporting %(var_name)s "
                                             "%(var_value)s") % {
                                             "pkg": fmri_list[j],
@@ -664,7 +783,8 @@
         try:
                 action_lists = list(manifest.Manifest.comm(manifest_list))
         except manifest.ManifestError, e:
-                error("Duplicate action(s) in package \"%s\": \n%s" %
+                raise PkgmergeException(
+                    "Duplicate action(s) in package \"%s\": \n%s" %
                     (new_fmri.pkg_name, e))
 
         # Declare new package FMRI.
@@ -790,7 +910,7 @@
                         fmris.append(fmri)
                 except (pkg.fmri.FmriError,
                     pkg.version.VersionError), e:
-                        error(str(e))
+                        raise PkgmergeException(str(e))
 
         # Create a dictionary of patterns, with each value being a
         # dictionary of pkg names & fmris that match that pattern.
--- a/src/util/publish/pkgmogrify.py	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/util/publish/pkgmogrify.py	Wed Aug 14 11:12:35 2013 +0530
@@ -34,6 +34,7 @@
 import warnings
 
 import pkg.actions
+import pkg.misc as misc
 from pkg.misc import PipeError
 
 macros  = {}
@@ -78,8 +79,9 @@
                         attrdict[a] = re.compile(attrdict[a])
                 except re.error, e:
                         raise RuntimeError, \
-                            _("transform (%s) has regexp error (%s) in matching clause"
-                            ) % (transform, e)
+                            _("transform (%(transform)s) has regexp error "
+                            "(%(err)s) in matching clause"
+                            ) % {"transform": transform, "err": e}
 
         op = s[index+2:].strip().split(None, 1)
 
@@ -190,6 +192,11 @@
                 operation = add_func
 
         elif op[0] == "edit":
+                if len(op) < 2:
+                        raise RuntimeError, \
+                            _("transform (%s) has 'edit' operation syntax error"
+                            ) % transform
+
                 args = shlex.split(op[1])
                 if len(args) not in [2, 3]:
                         raise RuntimeError, \
@@ -209,8 +216,9 @@
                         regexp = args[1]
                 except re.error, e:
                         raise RuntimeError, \
-                            _("transform (%s) has 'edit' operation with malformed"
-                              "regexp (%s)") % (transform, e)
+                            _("transform (%(transform)s) has 'edit' operation "
+                            "with malformed regexp (%(err)s)") % \
+                            {"transform": transform, "err": e}
 
                 if len(args) == 3:
                         replace = args[2]
@@ -243,13 +251,20 @@
                                 ]
                         except re.error, e:
                                 raise RuntimeError, \
-                                    _("transform (%s) has edit operation with replacement"
-                                      "string regexp error %e") % (transform, e)
+                                    _("transform (%(transform)s) has edit "
+                                    "operation with replacement string regexp "
+                                    "error %(err)e") % \
+                                    {"transform": transform, "err": e}
                         return action
 
                 operation = replace_func
 
         elif op[0] == "delete":
+                if len(op) < 2:
+                        raise RuntimeError, \
+                            _("transform (%s) has 'delete' operation syntax error"
+                            ) % transform
+
                 args = shlex.split(op[1])
                 if len(args) != 2:
                         raise RuntimeError, \
@@ -261,8 +276,9 @@
                         regexp = re.compile(args[1])
                 except re.error, e:
                         raise RuntimeError, \
-                            _("transform (%s) has 'edit' operation with malformed"
-                            "regexp (%s)") % (transform, e)
+                            _("transform (%(transform)s) has 'delete' operation"
+                            "with malformed regexp (%(err)s)") % \
+                            {"transform": transform, "err": e}
 
                 def delete_func(action, matches, pkg_attrs, filename, lineno):
                         val = attrval_as_list(action.attrs, attr)
@@ -281,8 +297,10 @@
                                         del action.attrs[attr]
                         except re.error, e:
                                 raise RuntimeError, \
-                                    _("transform (%s) has edit operation with replacement"
-                                      "string regexp error %e") % (transform, e)
+                                    _("transform (%(transform)s) has delete "
+                                    "operation with replacement string regexp "
+                                    "error %(err)e") % \
+                                    {"transform": transform, "err": e}
                         return action
 
                 operation = delete_func
@@ -443,8 +461,9 @@
                 ref = int(i.string[slice(*i.span())][2:-1])
 
                 if ref == 0 or ref > len(backrefs) - 1:
-                        raise RuntimeError, _("no match group %d (max %d)") % \
-                            (ref, len(backrefs) - 1)
+                        raise RuntimeError, _("no match group %(group)d "
+                            "(max %(maxgroups)d)") % \
+                            {"group": ref, "maxgroups": len(backrefs) - 1}
 
                 newmsg += msg[prevend:i.start()] + backrefs[ref]
                 prevend = i.end()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/publish/pkgsurf.py	Wed Aug 14 11:12:35 2013 +0530
@@ -0,0 +1,809 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# pkgsurf - Detailed operation description:
+#
+# After determining the packages present in the target repo, pkgsurf tries to
+# find the associated version of each package in the reference repo. Packages
+# which can't be found in the reference are ignored (not reversioned). Only the
+# latest version of the reference packages are considered. 
+# We then compare the target and ref manifest for content changes. Any
+# difference in the manifests' actions is considered a content change unless
+# they differ in:
+#  - the pkg FMRI (since this is what we'll adjust anyway)
+#  - a set action whose name attribute is specified with -i/--ignore
+#  - a signature action (signature will change when FMRI changes)
+#  - a depend action (see below)
+#   
+# Changes in depend actions are not considered a content change, however,
+# further analysis is required since the package can only be reversioned if the
+# dependency package didn't have a content change and its dependencies didn't
+# have a content change either.
+#
+# For the depend actions it is therefore required to recurse through the whole
+# dependency chain to determine a content change. Only if no package in the
+# chain had a content change the can the manifest be reversioned.
+#
+# Reversioning certain packages will break the inter-dependency integrity of the
+# target repo since certain package versions might not be available any longer.
+# Therefore pkgsurf will go through all depend actions in the repo and, if they
+# point to a reversioned package, adjust them to the correct version.
+# This requires that signature actions in these adjusted packages need to be
+# dropped since the manifest data changed.
+#
+# In the regular case, the new dependency FMRI of a certain package is taken
+# from the associated manifest of the reference version of this package.
+# However, if dependencies got added/removed it might not be found. In this case
+# pkgsurf uses the FMRI of the actual package which got reversioned as the new
+# dependency FMRI.
+#
+# pkgsurf deletes and inserts manifests in place for the target repo. File data
+# does not need to be modified since we only operate on packages with no content
+# change. It runs a catalog rebuild as the last step to regain catalog integrity
+# within the repo. 
+
+import getopt
+import gettext
+import locale
+import os
+import shutil
+import sys
+import tempfile
+import traceback
+
+from itertools import repeat
+
+import pkg.actions as actions
+import pkg.client.api_errors as api_errors
+import pkg.client.pkgdefs as pkgdefs
+import pkg.client.progress as progress
+import pkg.client.publisher as publisher
+import pkg.client.transport.transport as transport
+import pkg.fmri as fmri
+import pkg.manifest as manifest
+import pkg.misc as misc
+import pkg.portable as portable
+import pkg.server.repository as sr
+
+from pkg.client import global_settings
+from pkg.misc import emsg, msg, PipeError
+
+PKG_CLIENT_NAME = "pkgsurf"
+
+temp_root = None
+repo_modified = False
+repo_finished = False
+repo_uri = None
+
+def error(text, cmd=None):
+        """Emit an error message prefixed by the command name """
+
+        if cmd:
+                text = "\n%s: %s" % (cmd, text)
+
+        else:
+                text = "\n%s: %s" % (PKG_CLIENT_NAME, text)
+
+
+        # If the message starts with whitespace, assume that it should come
+        # *before* the command-name prefix.
+        text_nows = text.lstrip()
+        ws = text[:len(text) - len(text_nows)]
+
+        # This has to be a constant value as we can't reliably get our actual
+        # program name on all platforms.
+        emsg(ws + text_nows)
+
+def cleanup(no_msg=False):
+	"""Remove temporary directories. Print error msg in case operation
+        was not finished."""
+
+        global temp_root
+
+        if repo_modified and not repo_finished and not no_msg:
+                error(_("""
+The target repository has been modified but the operation did not finish
+successfully. It is now in an inconsistent state.
+
+To re-try the operation, run the following commands:
+  /usr/bin/pkgrepo rebuild -s %(repo)s --no-index
+  %(argv)s
+""") % {"repo": repo_uri, "argv": " ".join(sys.argv)})
+
+        if temp_root:
+                shutil.rmtree(temp_root)
+                temp_root = None
+
+def usage(usage_error=None, cmd=None, retcode=pkgdefs.EXIT_BADOPT):
+        """Emit a usage message and optionally prefix it with a more specific
+        error message.  Causes program to exit."""
+
+        if usage_error:
+                error(usage_error, cmd=cmd)
+
+        emsg(_("""\
+Usage:
+        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]
+            [-c pattern ...]
+
+Options:
+        -c pattern      Treat every package whose FMRI matches 'pattern' as 
+                        changed and do not reversion it. Can be specified
+                        multiple times.
+
+        -i name         Ignore set actions with the name field set to 'name' for
+                        determination of content change.  Can be specified
+                        multiple times.
+
+        -n              Perform a trial run with no changes made.
+
+        -p publisher    Only operate on given publisher. Can be specified
+                        multiple times.
+
+        -r ref_uri      URI of reference repository.
+
+        -s target_path  Path to target repository. Repository should only
+                        contain one version of each package. Must be a
+                        filesystem-based repository.
+
+        -?/--help       Print this message.
+"""))
+
+
+        sys.exit(retcode)
+
+def abort(err=None, retcode=pkgdefs.EXIT_OOPS):
+        """To be called when a fatal error is encountered."""
+
+        if err:
+                # Clear any possible output first.
+                msg("")
+                error(err)
+
+        cleanup()
+        sys.exit(retcode)
+
+def fetch_catalog(src_pub, xport, temp_root):
+        """Fetch the catalog from src_uri."""
+
+        if not src_pub.meta_root:
+                # Create a temporary directory for catalog.
+                cat_dir = tempfile.mkdtemp(dir=temp_root)
+                src_pub.meta_root = cat_dir
+
+        src_pub.transport = xport
+        src_pub.refresh(full_refresh=True, immediate=True)
+
+        return src_pub.catalog
+
+def get_latest(cat):
+        """ Get latest packages (surface) from given catalog.
+        Returns a dict of the form:
+                { pkg-name: pkg-fmri, ... }
+        """
+        matching, ref, unmatched = cat.get_matching_fmris(["*@latest"])
+
+        del ref
+
+        matches = {}
+        for m in matching:
+                matches[m] = matching[m][0]
+
+        return matches
+
+def get_matching_pkgs(cat, patterns):
+        """Get the matching pkg FMRIs from catalog 'cat' based on the input
+        patterns 'patterns'."""
+
+        versions = set()
+        for p in patterns:
+                if "@" in p:
+                     versions.add(p)
+
+        if versions:
+                msg = _("Packages specified to not be reversioned cannot "
+                    "contain versions:\n\t")
+                msg += "\n\t".join(versions)
+                abort(msg)
+
+        matching, ref, unmatched = cat.get_matching_fmris(patterns)
+
+        if unmatched:
+                msg = _("The specified packages were not found in the "
+                    "repository:\n\t")
+                msg += "\n\t".join(unmatched)
+                abort(msg)
+
+        return matching.keys()
+
+def get_manifest(repo, pub, pfmri):
+        """ Retrieve a manifest with FMRI 'pfmri' of publisher 'pub' from
+        repository object 'repo'. """
+
+        path = repo.manifest(pfmri, pub)
+        mani = manifest.Manifest(pfmri)
+        try:
+                mani.set_content(pathname=path)
+        except Exception, e:
+                abort(err=_("Can not open manifest file %(file)s: %(err)s\n"
+                    "Please run 'pkgrepo verify -s %(rroot)s' to check the "
+                    "integrity of the repository.") \
+                    % {"file": path, "err": str(e), "rroot": repo.root})
+        return mani
+
+def get_tracker():
+        try:
+                progresstracker = \
+                    progress.FancyUNIXProgressTracker()
+        except progress.ProgressTrackerException:
+                progresstracker = progress.CommandLineProgressTracker()
+        progresstracker.set_major_phase(progresstracker.PHASE_UTILITY)
+        return progresstracker
+
+def subs_undef_fmri_str(fmri_str, latest_ref_pkgs):
+        """ Substitute correct dependency FMRI if no counterpart can be found in
+        the reference manifest. Use the original FMRI in case the current
+        version of dependency pkg in the repo is still a successor of the
+        specified dependency FMRI, otherwise substitute the complete version of
+        the pkg currently present in the repo."""
+
+        dpfmri = fmri.PkgFmri(fmri_str, "5.11")
+        ndpfmri = latest_ref_pkgs[dpfmri.get_name()]
+
+        if ndpfmri.is_successor(dpfmri):
+                return fmri_str
+
+        return ndpfmri.get_short_fmri(anarchy=True)
+
+def get_dep_fmri_str(fmri_str, pkg, act, latest_ref_pkgs, reversioned_pkgs,
+    ref_xport):
+        """Get the adjusted dependency FMRI of package 'pkg' specified in
+        action 'act' based on if the FMRI belongs to a reversioned package or
+        not. 'fmri_str' contains the original FMRI string from the manifest to
+        be adjusted. This has to be passed in separately since in case of
+        require-any dependencies an action can contain multiple FMRIs. """
+
+        dpfmri = fmri.PkgFmri(fmri_str, "5.11")
+
+        # Versionless dependencies don't need to be changed.
+        if not dpfmri.version:
+                return fmri_str
+
+        # Dep package hasn't been changed, no adjustment necessary.
+        if dpfmri.get_pkg_stem() not in reversioned_pkgs:
+                return fmri_str                
+
+        # Find the dependency action of the reference package
+        # and replace the current version with it.
+        try:
+                ref_mani = ref_xport.get_manifest(latest_ref_pkgs[pkg])
+        except KeyError:
+                # This package is not in the ref repo so we just substitute the
+                # dependency.
+                return subs_undef_fmri_str(fmri_str, latest_ref_pkgs)
+
+        for ra in ref_mani.gen_actions_by_type("depend"):
+                # Any difference other than the FMRI means we
+                # can't use this action as a reference.
+                diffs = act.differences(ra)
+                if "fmri" in diffs:
+                        diffs.remove("fmri")
+                if diffs:
+                        continue
+
+                fmris = ra.attrlist("fmri")
+
+                for rf in fmris:
+                        rpfmri = fmri.PkgFmri(rf, "5.11")
+                        if rpfmri.get_pkg_stem() != dpfmri.get_pkg_stem():
+                                continue
+
+                        # Only substitute dependency if it actually
+                        # changed.
+                        if not rpfmri.version \
+                            or rpfmri.get_version() != dpfmri.get_version():
+                                return rf
+
+                        return fmri_str
+
+        # If a varcet changed we might not find the matching action.
+        return subs_undef_fmri_str(fmri_str, latest_ref_pkgs)
+
+def adjust_dep_action(pkg, act, latest_ref_pkgs, reversioned_pkgs, ref_xport):
+        """Adjust dependency FMRIs of action 'act' if it is of type depend.
+        The adjusted action will reference only FMRIs which are present in the
+        reversioned repo. """
+
+        modified = False
+
+        # Drop signatures (changed dependency will void signature value).
+        if act.name == "signature":
+                return
+        # Ignore anything other than depend actions.
+        elif act.name != "depend":
+                return act
+
+        # Require-any deps are list so convert every dep FMRI into a list.
+        fmris = act.attrlist("fmri")
+
+        new_dep = []
+        for f in fmris:
+                new_f = get_dep_fmri_str(f, pkg, act, latest_ref_pkgs,
+                    reversioned_pkgs, ref_xport)
+                if not modified and f != new_f:
+                        modified = True
+                new_dep.append(new_f)
+
+        if not modified:
+                return act
+
+        if len(new_dep) == 1:
+                new_dep = new_dep[0]
+
+        nact = actions.fromstr(str(act))
+        nact.attrs["fmri"] = new_dep
+
+        return nact
+
+def use_ref(a, deps, ignores):
+        """Determine if the given action indicates that the pkg can be
+        reversioned."""
+
+        if a.name == "set" and "name" in a.attrs:
+                if a.attrs["name"] in ignores:
+                        return True
+                # We ignore the pkg FMRI because this is what 
+                # will always change.
+                if a.attrs["name"] == "pkg.fmri":
+                        return True
+
+        # Signature will always change.
+        if a.name == "signature":
+                return True
+
+        if a.name == "depend":
+                # TODO: support dependency lists
+                # For now, treat as content change.
+                if not isinstance(a.attrs["fmri"], basestring):
+                        return False
+                dpfmri = fmri.PkgFmri(a.attrs["fmri"], "5.11")
+                deps.add(dpfmri.get_pkg_stem())
+                return True
+
+        return False
+
+def do_reversion(pub, ref_pub, target_repo, ref_xport, changes, ignores):
+        """Do the repo reversion.
+        Return 'True' if repo got modified, 'False' otherwise."""
+
+        global temp_root, tracker, dry_run, repo_finished, repo_modified
+
+        target_cat = target_repo.get_catalog(pub=pub)
+        ref_cat = fetch_catalog(ref_pub, ref_xport, temp_root)
+
+        latest_pkgs = get_latest(target_cat)
+        latest_ref_pkgs = get_latest(ref_cat)
+
+        no_revs = get_matching_pkgs(target_cat, changes)
+
+        # We use bulk prefetching for faster transport of the manifests.
+        # Prefetch requires an intent which it sends to the server. Here
+        # we just use operation=reversion for all FMRIs.
+        intent = "operation=reversion;"
+        ref_pkgs = zip(latest_ref_pkgs.values(), repeat(intent))
+
+        # Retrieve reference manifests.
+        # Try prefetching manifests in bulk first for faster, parallel
+        # transport. Retryable errors during prefetch are ignored and
+        # manifests are retrieved again during the "Reading" phase.
+        ref_xport.prefetch_manifests(ref_pkgs, progtrack=tracker)
+
+        # Need to change the output of mfst_fetch since otherwise we
+        # would see "Download Manifests x/y" twice, once from the
+        # prefetch and once from the actual manifest analysis.
+        tracker.mfst_fetch = progress.GoalTrackerItem(_("Analyzing Manifests"))
+
+        tracker.manifest_fetch_start(len(latest_pkgs))
+
+        reversioned_pkgs = set()
+        depend_changes = {}
+        dups = 0   # target pkg has equal version to ref pkg
+        new_p = 0  # target pkg not in ref
+        sucs = 0   # ref pkg is successor to pkg in targ
+        nrevs = 0  # pkgs requested to not be reversioned by user
+
+        for p in latest_pkgs:
+                # First check if the package is in the list of FMRIs the user
+                # doesn't want to reversion.
+                if p in no_revs:
+                        nrevs += 1
+                        tracker.manifest_fetch_progress(completion=True)
+                        continue
+
+                # Check if the package is in the ref repo, if not: ignore.
+                if not p in latest_ref_pkgs:
+                        new_p += 1
+                        tracker.manifest_fetch_progress(completion=True)
+                        continue
+
+                pfmri = latest_pkgs[p]
+                # Ignore if latest package is the same in targ and ref.
+                if pfmri == latest_ref_pkgs[p]:
+                        dups += 1
+                        tracker.manifest_fetch_progress(completion=True)
+                        continue
+
+                # Ignore packages where ref version is higher.
+                if latest_ref_pkgs[p].is_successor(pfmri):
+                        sucs += 1
+                        tracker.manifest_fetch_progress(completion=True)
+                        continue
+
+                # Pull the manifests for target and ref repo.
+                dm = get_manifest(target_repo, pub, pfmri)
+                rm = ref_xport.get_manifest(latest_ref_pkgs[p])
+                tracker.manifest_fetch_progress(completion=True)
+
+                tdeps = set()
+                rdeps = set()
+
+                # Diff target and ref manifest.
+                # action only in targ, action only in ref, common action
+                ta, ra, ca = manifest.Manifest.comm([dm, rm])
+
+                # Check for manifest changes.
+                if not all(use_ref(a, tdeps, ignores) for a in ta) \
+                    or not all(use_ref(a, rdeps, ignores) for a in ra):
+                        continue
+
+                # Both dep lists should be equally long in case deps have just 
+                # changed. If not, it means a dep has been added or removed and
+                # that means content change.
+                if len(tdeps) != len(rdeps):
+                        continue
+
+                # If len is not different we still have to make sure that 
+                # entries have the same pkg stem. The test above just saves time
+                # in some cases.
+                if not all(td in rdeps for td in tdeps):
+                        continue
+
+                # Pkg only contains dependency change. Keep for further
+                # analysis.
+                if tdeps:
+                        depend_changes[pfmri.get_pkg_stem(
+                            anarchy=True)] = tdeps
+                        continue
+
+                # Pkg passed all checks and can be reversioned.
+                reversioned_pkgs.add(pfmri.get_pkg_stem(anarchy=True))
+
+        tracker.manifest_fetch_done()
+
+        def has_changed(pstem, seen=None, depth=0):
+                """Determine if a package or any of its dependencies has
+                changed.
+                Function will check if a dependency had a content change. If it
+                only had a dependency change, analyze its dependencies 
+                recursively. Only if the whole dependency chain didn't have any
+                content change it is safe to reversion the package. 
+
+                Note about circular dependencies: The function keeps track of 
+                pkgs it already processed by stuffing them into the set 'seen'.
+                However, 'seen' gets updated before the child dependencies of 
+                the current pkg are examined. This works if 'seen' is only used
+                for one dependency chain since the function immediately comes 
+                back with a True result if a pkg has changed further down the
+                tree. However, if 'seen' is re-used between runs, it will
+                return prematurely, likely returning wrong results. """
+
+                MAX_DEPTH = 100
+
+                if not seen:
+                        seen = set()
+
+                if pstem in seen:
+                        return False
+
+                depth += 1
+                if depth > MAX_DEPTH:
+                        # Let's make sure we don't run into any
+                        # recursion limits. If the dep chain is too deep
+                        # just treat as changed pkg.
+                        error(_("Dependency chain depth of >%(md)d detected for"
+                            " %(p)s." % {"md": MAX_DEPTH, "p": p}))
+                        return True
+
+                # Pkg has no change at all.
+                if pstem in reversioned_pkgs:
+                        return False
+
+                # Pkg must have content change, if it had no change it would be
+                # in reversioned_pkgs, and if it had just a dep change it would
+                # be in depend_changes.
+                if pstem not in depend_changes:
+                        return True
+
+                # We need to update 'seen' here, otherwise we won't find this
+                # entry in case of a circular dependency.
+                seen.add(pstem)
+
+                return any(
+                    has_changed(d, seen, depth)
+                    for d in depend_changes[pstem]
+                )
+
+        # Check if packages which just have a dep change can be reversioned by
+        # checking if child dependencies also have no content change.
+        dep_revs = 0
+        for p in depend_changes:
+                if not has_changed(p):
+                        dep_revs += 1
+                        reversioned_pkgs.add(p)
+
+        status = []
+        status.append((_("Packages to process:"), str(len(latest_pkgs))))
+        status.append((_("New packages:"), str(new_p)))
+        status.append((_("Unmodified packages:"), str(dups)))
+        if sucs:
+                # This only happens if reference repo is ahead of target repo,
+                # so only show if it actually happened.
+                status.append((_("Packages with successors in "
+                    "reference repo:"), str(sucs)))
+        if nrevs:
+                # This only happens if user specified pkgs to not revert,
+                # so only show if it actually happened.
+                status.append((_("Packages not to be reversioned by user "
+                    "request:"), str(nrevs)))
+        status.append((_("Packages with no content change:"),
+            str(len(reversioned_pkgs) - dep_revs)))
+        status.append((_("Packages which only have dependency change:"),
+            str(len(depend_changes))))
+        status.append((_("Packages with unchanged dependency chain:"),
+            str(dep_revs)))
+        status.append((_("Packages to be reversioned:"),
+            str(len(reversioned_pkgs))))
+
+        rjust_status = max(len(s[0]) for s in status)
+        rjust_value = max(len(s[1]) for s in status)
+        for s in status:
+                msg("%s %s" % (s[0].rjust(rjust_status),
+                    s[1].rjust(rjust_value)))
+
+        if not reversioned_pkgs:
+                msg(_("\nNo packages to reversion."))
+                return False
+
+        if dry_run:
+                msg(_("\nReversioning packages (dry-run)."))
+        else:
+                msg(_("\nReversioning packages."))
+
+        # Start the main pass. Reversion packages from reversioned_pkgs to the
+        # version in the ref repo. For packages which don't get reversioned,
+        # check if the dependency versions are still correct, fix if necessary.
+        tracker.reversion_start(len(latest_pkgs), len(reversioned_pkgs))
+
+        for p in latest_pkgs:
+                tracker.reversion_add_progress(pfmri, pkgs=1)
+                modified = False
+
+                # Get the pkg fmri (pfmri) of the latest version based on if it
+                # has been reversioned or not.
+                stem = latest_pkgs[p].get_pkg_stem(anarchy=True)
+                if stem in reversioned_pkgs:
+                        tracker.reversion_add_progress(pfmri, reversioned=1)
+                        if dry_run:
+                                continue
+                        pfmri = latest_ref_pkgs[p]
+                        # Retrieve manifest from ref repo and replace the one in
+                        # the target repo. We don't have to adjust depndencies
+                        # for these packages because they will not depend on
+                        # anything we'll reversion.
+                        rmani = ref_xport.get_manifest(pfmri)
+                        opath = target_repo.manifest(latest_pkgs[p], pub)
+                        os.remove(opath)
+                        path = target_repo.manifest(pfmri, pub)
+                        try:
+                                repo_modified = True
+                                repo_finished = False
+                                portable.rename(rmani.pathname, path)
+                        except OSError, e:
+                                abort(err=_("Could not reversion manifest "
+                                    "%(path)s: %(err)s") % (path, str(e)))
+                        continue
+
+                # For packages we don't reversion we have to check if they 
+                # depend on a reversioned package.
+                # Since the version of this dependency might be removed from the
+                # repo, we have to adjust the dep version to the one of the
+                # reversioned pkg.
+                pfmri = latest_pkgs[p]
+                omani = get_manifest(target_repo, pub, pfmri)
+                mani = manifest.Manifest(pfmri)
+                for act in omani.gen_actions():
+                        nact = adjust_dep_action(p, act, latest_ref_pkgs,
+                            reversioned_pkgs, ref_xport)
+                        if nact:
+                                mani.add_action(nact, misc.EmptyI)
+                                if nact is not act:
+                                        modified = True
+
+                # Only touch manifest if something actually changed.
+                if modified:
+                        tracker.reversion_add_progress(pfmri, adjusted=1)
+                        if not dry_run:
+                                path = target_repo.manifest(pfmri, pub)
+                                repo_modified = True
+                                repo_finished = False
+                                mani.store(path)
+        tracker.reversion_done()
+
+        return True
+
+def main_func():
+
+        global temp_root, repo_modified, repo_finished, repo_uri, tracker
+        global dry_run
+
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        global_settings.client_name = PKG_CLIENT_NAME
+
+        try:
+                opts, pargs = getopt.getopt(sys.argv[1:], "?c:i:np:r:s:",
+                    ["help"])
+        except getopt.GetoptError, e:
+                usage(_("illegal option -- %s") % e.opt)
+
+        dry_run = False
+        ref_repo_uri = None
+        repo_uri = os.getenv("PKG_REPO", None)
+        changes = set()
+        ignores = set()
+        publishers = set()
+        
+        processed_pubs = 0
+
+        for opt, arg in opts:
+                if opt == "-c":
+                        changes.add(arg)
+                elif opt == "-i":
+                        ignores.add(arg)
+                elif opt == "-n":
+                        dry_run = True
+                elif opt == "-p":
+                        publishers.add(arg)
+                elif opt == "-r":
+                        ref_repo_uri = misc.parse_uri(arg)
+                elif opt == "-s":
+                        repo_uri = misc.parse_uri(arg)
+                elif opt == "-?" or opt == "--help":
+                        usage(retcode=pkgdefs.EXIT_OK)
+
+        if pargs:
+                usage(_("Unexpected argument(s): %s") % " ".join(pargs))
+
+        if not repo_uri:
+                usage(_("A target repository must be provided."))
+
+        if not ref_repo_uri:
+                usage(_("A reference repository must be provided."))
+
+        t = misc.config_temp_root()
+        temp_root = tempfile.mkdtemp(dir=t,
+            prefix=global_settings.client_name + "-")
+
+        ref_incoming_dir = tempfile.mkdtemp(dir=temp_root)
+        ref_pkg_root = tempfile.mkdtemp(dir=temp_root)
+
+        ref_xport, ref_xport_cfg = transport.setup_transport()
+        ref_xport_cfg.incoming_root = ref_incoming_dir
+        ref_xport_cfg.pkg_root = ref_pkg_root
+        transport.setup_publisher(ref_repo_uri, "ref", ref_xport,
+            ref_xport_cfg, remote_prefix=True)
+
+        target = publisher.RepositoryURI(misc.parse_uri(repo_uri))
+        if target.scheme != "file":
+                abort(err=_("Target repository must be filesystem-based."))
+        try:
+                target_repo = sr.Repository(read_only=dry_run,
+                    root=target.get_pathname())
+        except sr.RepositoryError, e:
+                abort(str(e))
+
+        tracker = get_tracker()
+
+        for pub in target_repo.publishers:
+                if publishers and pub not in publishers \
+                    and '*' not in publishers:
+                        continue
+
+                msg(_("Processing packages for publisher %s ...") % pub)
+                # Find the matching pub in the ref repo.
+                for ref_pub in ref_xport_cfg.gen_publishers():
+                        if ref_pub.prefix == pub:
+                                found = True
+                                break
+                else:
+                        txt = _("Publisher %s not found in reference "
+                            "repository.") % pub
+                        if publishers:
+                                abort(err=txt)
+                        else:
+                                txt += _(" Skipping.")
+                                msg(txt)
+                        continue
+
+                processed_pubs += 1
+
+                rev = do_reversion(pub, ref_pub, target_repo, ref_xport,
+                    changes, ignores)
+
+                # Only rebuild catalog if anything got actually reversioned.
+                if rev and not dry_run:
+                        msg(_("Rebuilding repository catalog."))
+                        target_repo.rebuild(pub=pub)
+                repo_finished = True
+
+        ret = pkgdefs.EXIT_OK
+        if processed_pubs == 0:
+                msg(_("No matching publishers could be found."))
+                ret = pkgdefs.EXIT_OOPS
+        cleanup()
+        return ret
+
+
+#
+# Establish a specific exit status which means: "python barfed an exception"
+# so that we can more easily detect these in testing of the CLI commands.
+#
+if __name__ == "__main__":
+        try:
+                __ret = main_func()
+        except PipeError:
+                # We don't want to display any messages here to prevent
+                # possible further broken pipe (EPIPE) errors.
+                cleanup(no_msg =True)
+                __ret = pkgdefs.EXIT_OOPS
+        except (KeyboardInterrupt, api_errors.CanceledException):
+                cleanup()
+                __ret = pkgdefs.EXIT_OOPS
+        except (actions.ActionError, RuntimeError,
+            api_errors.ApiException), _e:
+                error(_e)
+                cleanup()
+                __ret = pkgdefs.EXIT_OOPS
+        except SystemExit, _e:
+                cleanup()
+                raise _e
+        except:
+                traceback.print_exc()
+                error(misc.get_traceback_message())
+                __ret = 99
+        sys.exit(__ret)
--- a/src/web/en/base.shtml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/web/en/base.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 ##
 ## CDDL HEADER END
 ##
-## Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+## Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 ##
 <%!
         import pkg.server.api as api
@@ -49,7 +49,14 @@
         if g_vars["config"].mirror:
                 # Only statistics are available in mirror mode.
                 return [("stats.shtml", "Statistics")]
-
+        if g_vars["http_depot"]:
+                # Apache can't return statistics via the BUI
+                # but does have a top level list of all repositories.
+                return [
+                    ("/", "Repositories"),
+                    ("catalog.shtml", "Packages"),
+                    ("search.shtml", "Search"),
+                ]
         return [
                 ("catalog.shtml", "Packages"),
                 ("search.shtml", "Search"),
--- a/src/web/en/catalog.shtml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/web/en/catalog.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 ##
 ## CDDL HEADER END
 ##
-## Copyright 2009, 2012 Oracle and/or its affiliates. All rights reserved.
+## Copyright 2009, 2013 Oracle and/or its affiliates. All rights reserved.
 ##
 <%!
         import pkg.fmri
@@ -236,9 +236,8 @@
                 # packagemanager requires it and shouldn't.
                 p5ihref = self.shared.rpath(g_vars, "p5i/0/%s.p5i" % (
                     urllib.quote(pfmri.pkg_name, ""))) 
-                mhref = self.shared.rpath(g_vars, "manifest/0/%s" % (
-                    urllib.quote(pfmri.get_fmri(include_scheme=False,
-                    anarchy=True), "")))
+                mhref = self.shared.rpath(g_vars,
+                    "manifest/0/%s" % (pfmri.get_url_path()))
 %>
                         <tr${rclass}>
                                 <td scope="row">
--- a/src/web/en/index.shtml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/web/en/index.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 ##
 ## CDDL HEADER END
 ##
-## Copyright 2008, 2012 Oracle and/or its affiliates. All rights reserved.
+## Copyright 2008, 2013 Oracle and/or its affiliates. All rights reserved.
 ##
 <%inherit file="layout.shtml"/>\
 <%page args="g_vars"/>\
@@ -27,6 +27,7 @@
         catalog = g_vars["catalog"]
         config = g_vars["config"]
         request = g_vars["request"]
+        http_depot = g_vars["http_depot"]
 %>\
 <%def name="page_title(g_vars)"><%
         req = g_vars["request"]
@@ -132,7 +133,7 @@
         </div>
 </div>
 <div class="yui-b">
-% if not config.mirror and request.publisher:
+% if not config.mirror and not http_depot and request.publisher:
         <table class="stats" summary="A summary of information about the
  package repository.">
                 <tr class="first">
--- a/src/web/en/search.shtml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/web/en/search.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 ##
 ## CDDL HEADER END
 ##
-## Copyright 2010, 2012 Oracle and/or its affiliates. All rights reserved.
+## Copyright 2010, 2013 Oracle and/or its affiliates. All rights reserved.
 ##
 <%!
         import itertools
@@ -36,6 +36,7 @@
 <%
         catalog = g_vars["catalog"]
         request = g_vars["request"]
+        http_depot = g_vars["http_depot"]
 %>\
 <%def name="page_title(g_vars)"><%
         return "Package Search"
@@ -279,6 +280,12 @@
                         # depot server).
                         uri = request.url(qs=request.query_string,
                             relative=True)
+                        if http_depot:
+                                # if using the http-depot, we need to redirect
+                                # to the appropriate repository within the
+                                # webapp.
+                                lang = request.path_info.split("/")[1]
+                                uri = "/depot/%s/%s/%s" % (http_depot, lang, uri)
                         scheme, netloc, path, params, query, \
                             fragment = urlparse.urlparse(uri)
 
@@ -349,9 +356,9 @@
                         # XXX the .p5i extension is a bogus hack because
                         # packagemanager requires it and shouldn't.
                         p5ihref = self.shared.rpath(g_vars, "p5i/0/%s.p5i" % (
-                            urllib.quote(stem, ""))) 
-                        mhref = self.shared.rpath(g_vars, "manifest/0/%s" % (
-                            urllib.quote(pfmri_str, "")))
+                            urllib.quote(stem, "")))
+                        mhref = self.shared.rpath(g_vars,
+                            "manifest/0/%s" % pfmri.get_url_path())
 %>\
                         <tr${rclass}>
                                 <td>
--- a/src/web/index.shtml	Thu Jul 18 09:40:49 2013 -0700
+++ b/src/web/index.shtml	Wed Aug 14 11:12:35 2013 +0530
@@ -19,7 +19,7 @@
 ##
 ## CDDL HEADER END
 ##
-## Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+## Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 ##
 <%!
         import os.path
@@ -31,6 +31,7 @@
 <%page args="g_vars"/>\
 <%
         base = g_vars["base"]
+        http_depot = g_vars["http_depot"]
         config = api.ConfigInterface(CLIENT_API_VERSION, base)
         request = api.RequestInterface(CLIENT_API_VERSION, base)
 
@@ -65,6 +66,8 @@
                 if pub and not request.path_info.endswith("/"):
                         prefix = pub + "/"
                 rpath = "index.shtml"
+        if http_depot:
+                prefix = http_depot
 
         # Finally, redirect the client to the content appropriate for their
         # language and region.