#
# 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
# 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
#
#
#
import errno
import getopt
import gettext
import locale
import os
import six
import sys
import traceback
import warnings
import pkg
def format_update_error(e):
# This message is displayed to the user whenever an
# ImageFormatUpdateNeeded exception is encountered.
emsg("\n")
emsg(_("To continue, the target image must be upgraded "
"before it can be used. See pkg(1) update-format for more "
"information."))
"""Emit an error message prefixed by the command name """
if cmd:
else:
# If we get passed something like an Exception, we can convert
# it down to a string.
# If the message starts with whitespace, assume that it should come
# *before* the command-name prefix.
# This has to be a constant value as we can't reliably get our actual
# program name on all platforms.
"""Emit a usage message and optionally prefix it with a more specific
error message. Causes program to exit."""
if usage_error:
emsg (_("""\
Usage:
pkgdepend [options] command [cmd_options] [operands]
Subcommands:
pkgdepend generate [-IMm] -d dir [-d dir] [-D name=value] [-k path]
manifest_file
pkgdepend resolve [-EmoSv] [-d output_dir]
[-e external_package_file]... [-s suffix] manifest_file ...
Options:
-R dir
--help or -?
Environment:
PKG_IMAGE"""))
"""Produce a list of file dependencies from a manfiest and a proto
area."""
try:
["help"])
except getopt.GetoptError as e:
isa_paths = []
run_paths = []
platform_paths = []
dyn_tok_conv = {}
proto_dirs = []
if opt == "-d":
usage(_("The proto directory {0} could not be "
elif opt == "-D":
try:
except:
usage(_("-D arguments must be of the form "
"'name=value'."))
elif opt == "-I":
elif opt == "-k":
elif opt == "-m":
elif opt == "-M":
if show_usage:
usage(_("Generate only accepts one or two arguments."))
if "$ORIGIN" in dyn_tok_conv:
usage(_("ORIGIN may not be specified using -D. It will be "
"inferred from the\ninstall paths of the files."))
if not proto_dirs:
usage(_("At least one proto directory must be provided."),
try:
error(_("Could not parse manifest {manifest} because of the "
return EXIT_OOPS
except api_errors.ApiException as e:
error(e)
return EXIT_OOPS
if echo_manf:
for l in fh:
msg(d)
if show_missing:
for m in ms:
emsg(m)
for e in es:
emsg(e)
return retcode
"""Take a list of manifests and resolve any file dependencies, first
against the other published manifests and then against what is installed
on the machine."""
out_dir = None
suffix = None
constraint_files = []
try:
except getopt.GetoptError as e:
if opt == "-d":
elif opt == "-e":
elif opt == "-E":
elif opt == "-m":
elif opt == "-o":
elif opt == "-s":
elif opt == "-S":
elif opt == "-v":
usage(_("-o cannot be used with -d or -s"))
for manifest in manifest_paths:
if out_dir:
if img_dir == None:
orig_cwd = None
try:
except OSError:
# May be unreadable by user or have other problem.
pass
# It's assumed that this has been checked by the above
# function call and hasn't been removed from the
# environment.
if not img_dir:
error(_("Could not find image. Use the -R option or set "
"$PKG_IMAGE to the\nlocation of an image."))
return EXIT_OOPS
if constraint_files:
system_patterns = []
for f in constraint_files:
try:
for l in fh:
l = l.strip()
if l and not l.startswith("#"):
l)
except EnvironmentError as e:
cmd="resolve")
return EXIT_OOPS
raise api_errors._convert_error(e)
if not system_patterns:
error(_("External package list files were provided but "
"did not contain any fmri patterns."))
return EXIT_OOPS
elif use_system_to_resolve:
system_patterns = ["*"]
# Becuase building an ImageInterface permanently changes the cwd for
# python, it's necessary to do this step after resolving the paths to
# the manifests.
try:
except api_errors.ImageNotFoundException as e:
if e.user_specified:
if pkg_image_used:
error(_("No image rooted at '{0}' "
else:
e.user_dir))
else:
error(_("No image found."))
return EXIT_OOPS
except api_errors.PermissionsException as e:
error(e)
return EXIT_OOPS
except api_errors.ImageFormatUpdateNeeded as e:
# This should be a very rare error case.
return EXIT_OOPS
try:
error(_("Could not parse one or more manifests because of "
return EXIT_OOPS
except dependencies.DependencyError as e:
error(e)
return EXIT_OOPS
except api_errors.ApiException as e:
error(e)
return EXIT_OOPS
if output_to_screen:
elif out_dir:
else:
if constraint_files and unused_fmris:
msg(_("\nThe following fmris matched a pattern in a "
"constraint file but were not used in\ndependency "
"resolution:"))
if not constraint_files and external_deps:
msg(_("\nThe following fmris had dependencies resolve "
"to them:"))
for e in errs:
emsg(e)
for w in warnings:
emsg(w)
return ret_code
def __resolve_echo_line(l):
"""Given a line from a manifest, determines whether that line should
be repeated in the output file if echo manifest has been set."""
try:
except KeyboardInterrupt:
raise
except actions.ActionError:
return True
else:
try:
text = ""
act = ""
for l in fh:
text += l
continue
if __resolve_echo_line(act):
if strip_newline:
text += "\n"
text = ""
act = ""
text += "\n"
except EnvironmentError:
"""Write the resolved package dependencies to stdout.
'pkg_deps' is a dictionary that maps a path to a manifest to the
dependencies that were resolved for that manifest.
'manifest_paths' is a list of the paths to the manifests for which
file dependencies were resolved.
'echo_manifest' is a boolean which determines whether the original
manifest will be written out or not."""
for p in manifest_paths:
if not first:
msg("\n\n")
if echo_manifest:
for d in pkg_deps[p]:
msg(d)
return ret_code
"""Write the dependencies resolved, and possibly the manifest, to the
destination file.
'deps' is a list of the resolved dependencies.
'out_file' is the path to the destination file.
'echo_manifest' determines whether to repeat the original manifest in
the destination file.
'manifest_path' the path to the manifest which generated the
dependencies."""
try:
except EnvironmentError:
out_file))
return ret_code
if echo_manifest:
for d in deps:
return ret_code
"""Given an output directory, for each manifest given, writes the
dependencies resolved to a file in the output directory.
'pkg_deps' is a dictionary that maps a path to a manifest to the
dependencies that were resolved for that manifest.
'manifest_paths' is a list of the paths to the manifests for which
file dependencies were resolved.
'out_dir' is the path to the directory into which the dependency files
should be written.
'suffix' is the string to append to the end of each output file.
'echo_manifest' is a boolean which determines whether the original
manifest will be written out or not."""
try:
except EnvironmentError as e:
else:
emsg(_("Out dir {out_dir} does not exist and could "
return EXIT_OOPS
for p in manifest_paths:
if suffix:
if not ret_code:
return ret_code
"""Given an output directory, for each manifest given, writes the
dependencies resolved to a file in the output directory.
'pkg_deps' is a dictionary that maps a path to a manifest to the
dependencies that were resolved for that manifest.
'manifest_paths' is a list of the paths to the manifests for which
file dependencies were resolved.
'out_dir' is the path to the directory into which the dependency files
should be written.
'suffix' is the string to append to the end of each output file.
'echo_manifest' is a boolean which determines whether the original
manifest will be written out or not."""
if not suffix:
for p in manifest_paths:
if not ret_code:
return ret_code
def main_func():
try:
["help"])
except getopt.GetoptError as e:
img_dir = None
if opt == "-R":
subcommand = None
if pargs:
if subcommand == "help":
if show_usage:
elif not subcommand:
usage()
if subcommand == "generate":
if img_dir:
usage(_("generate subcommand doesn't use -R"))
elif subcommand == "resolve":
else:
#
# 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__":
# Make all warnings be errors.
# disable ResourceWarning: unclosed file
try:
except api_errors.MissingFileArgumentException as e:
error(_("The {cmd} command appears out of sync with the lib"
"is {client} while the library\nAPI version is {api}").format(
))
except api_errors.ApiException as e:
error(e)
except RuntimeError as _e:
except (PipeError, KeyboardInterrupt):
# We don't want to display any messages here to prevent
# possible further broken pipe (EPIPE) errors.
except SystemExit as _e:
raise _e
except: