--- a/src/man/pkgdepend.1.txt Fri Apr 02 16:42:17 2010 -0700
+++ b/src/man/pkgdepend.1.txt Fri Apr 02 19:53:57 2010 -0400
@@ -10,7 +10,7 @@
/usr/bin/pkgdepend generate [-IMm] [-D name=value] [-k path] manifest_path
proto_dir
- /usr/bin/pkgdepend resolve [-dmos] manifest_path ...
+ /usr/bin/pkgdepend resolve [-dmosv] manifest_path ...
DESCRIPTION
pkgdepend(1) is used to generate and resolve dependencies for
@@ -60,7 +60,7 @@
to look for kernel modules. Using the -k argument removes the
default paths which are /kernel and /usr/kernel.
- resolve [-mo] [-d output_dir] [-s suffix] manifest_path ...
+ resolve [-mov] [-d output_dir] [-s suffix] manifest_path ...
Transform dependencies on files into dependencies on the
packages which deliver those files. Dependencies are first
resolved against the manifests given on the command line and
@@ -84,6 +84,9 @@
will be added to the argument if not provided) to the basename
of the file that was the source of the resolved dependencies.
+ With -v, include additional package dependency debugging
+ metadata.
+
EXAMPLES
Example 1: Generate the dependencies for the manifest written in
foo, whose content directory is in ./bar/baz and store the results
--- a/src/modules/publish/dependencies.py Fri Apr 02 16:42:17 2010 -0700
+++ b/src/modules/publish/dependencies.py Fri Apr 02 19:53:57 2010 -0400
@@ -77,7 +77,7 @@
class UnresolvedDependencyError(DependencyError):
"""This exception is used when no package delivers a file which is
depended upon."""
-
+
def __init__(self, pth, file_dep, pvars):
self.path = pth
self.file_dep = file_dep
@@ -91,7 +91,7 @@
" ".join([("%s:%s" % (name, val)) for name, val in grp])
for grp in self.pvars.get_unsatisfied()
]))
-
+
def list_implicit_deps(file_path, proto_dir, dyn_tok_conv, kernel_paths,
remove_internal_deps=True):
"""Given the manifest provided in file_path, use the known dependency
@@ -150,7 +150,7 @@
delivered.setdefault(rp, variants.VariantSets()).merge(pvars)
bn = os.path.basename(p)
delivered_bn.setdefault(bn, variants.VariantSets()).merge(pvars)
-
+
for d in deps:
etype, pvars = d.resolve_internal(delivered_files=delivered,
delivered_base_names=delivered_bn)
@@ -302,7 +302,7 @@
'orig_dep_vars' is the original set of variants under which the
dependency must be satisfied.
-
+
'pkg_vars' is the list of variants against which the package delivering
the action was published."""
@@ -369,7 +369,7 @@
'orig_dep_vars' is the original set of variants under which the
dependency must be satisfied.
-
+
'pkg_vars' is the list of variants against which the package delivering
the action was published."""
@@ -648,14 +648,25 @@
dep.strip_variants()
return dep, dep_vars
-def resolve_deps(manifest_paths, api_inst):
+def prune_debug_attrs(action):
+ """Given a dependency action with pkg.debug.depend attributes
+ return a matching action with those attributes removed"""
+
+ attrs = dict((k, v) for k, v in action.attrs.iteritems()
+ if not k.startswith(base.Dependency.DEPEND_DEBUG_PREFIX))
+ return actions.depend.DependencyAction(**attrs)
+
+def resolve_deps(manifest_paths, api_inst, prune_attrs=False):
"""For each manifest given, resolve the file dependencies to package
dependencies. It returns a mapping from manifest_path to a list of
dependencies and a list of unresolved dependencies.
'manifest_paths' is a list of paths to the manifests being resolved.
- 'api_inst' is an ImageInterface which references the current image."""
+ 'api_inst' is an ImageInterface which references the current image.
+
+ 'prune_attrs' is a boolean indicating whether debugging
+ attributes should be stripped from returned actions."""
# The variable 'manifests' is a list of 5-tuples. The first element
# of the tuple is the path to the manifest. The second is the name of
@@ -736,6 +747,9 @@
# Add variant information to the dependency actions and combine
# what would otherwise be duplicate dependencies.
deps = combine(deps, pkg_vars)
+
+ if prune_attrs:
+ deps = [prune_debug_attrs(d) for d in deps]
pkg_deps[mp] = deps
-
+
return pkg_deps, errs
--- a/src/pkgdep.py Fri Apr 02 16:42:17 2010 -0700
+++ b/src/pkgdep.py Fri Apr 02 19:53:57 2010 -0400
@@ -79,7 +79,7 @@
Subcommands:
pkgdepend generate [-DIkMm] manifest proto_dir
- pkgdepend [options] resolve [-dMos] manifest ...
+ pkgdepend [options] resolve [-dmosv] manifest ...
Options:
-R dir
@@ -141,7 +141,7 @@
"inferred from the\ninstall paths of the files."))
retcode = 0
-
+
manf = pargs[0]
proto_dir = pargs[1]
@@ -167,14 +167,14 @@
for l in fh:
msg(l.rstrip())
fh.close()
-
+
for d in sorted(ds):
msg(d)
if show_missing:
for m in ms:
emsg(m)
-
+
for e in es:
emsg(e)
retcode = 1
@@ -188,8 +188,9 @@
echo_manifest = False
output_to_screen = False
suffix = None
+ verbose = False
try:
- opts, pargs = getopt.getopt(args, "d:mos:")
+ opts, pargs = getopt.getopt(args, "d:mos:v")
except getopt.GetoptError, e:
usage(_("illegal global option -- %s") % e.opt)
for opt, arg in opts:
@@ -201,6 +202,8 @@
output_to_screen = True
elif opt == "-s":
suffix = arg
+ elif opt == "-v":
+ verbose = True
if (out_dir or suffix) and output_to_screen:
usage(_("-o cannot be used with -d or -s"))
@@ -216,7 +219,7 @@
out_dir = os.path.abspath(out_dir)
if not os.path.isdir(out_dir):
usage(_("The output directory %s is not a directory." %
- manf), retcode=2)
+ out_dir), retcode=2)
if img_dir is None:
try:
@@ -249,14 +252,15 @@
return 1
try:
- pkg_deps, errs = dependencies.resolve_deps(manifest_paths, api_inst)
+ pkg_deps, errs = dependencies.resolve_deps(manifest_paths, api_inst,
+ prune_attrs=not verbose)
except (actions.MalformedActionError, actions.UnknownActionError), e:
error(_("Could not parse one or more manifests because of the " +
"following line:\n%s") % e.actionstr)
return 1
ret_code = 0
-
+
if output_to_screen:
ret_code = pkgdeps_to_screen(pkg_deps, manifest_paths,
echo_manifest)
@@ -297,7 +301,7 @@
attrs.update(dict(tup))
res.append(str(actions.depend.DependencyAction(**attrs)))
return "\n".join(res).rstrip()
-
+
def pkgdeps_to_screen(pkg_deps, manifest_paths, echo_manifest):
"""Write the resolved package dependencies to stdout.
--- a/src/tests/cli/t_pkgdep.py Fri Apr 02 16:42:17 2010 -0700
+++ b/src/tests/cli/t_pkgdep.py Fri Apr 02 19:53:57 2010 -0400
@@ -108,7 +108,7 @@
fp, self.py_path)
])))
return res
-
+
sp = subprocess.Popen(
"python%s -c 'import sys; print sys.path'" % ver,
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -157,7 +157,7 @@
"dummy_fmri": base.Dependency.DUMMY_FMRI,
"reason": "%(reason)s"
}
-
+
def make_full_res_manf_1(self, proto_area):
return self.make_res_manf_1(proto_area) + self.test_manf_1
@@ -187,7 +187,7 @@
"pfx":base.Dependency.DEPEND_DEBUG_PREFIX,
"dummy_fmri":base.Dependency.DUMMY_FMRI
}
-
+
def make_res_payload_1(self, proto_area):
return ("depend fmri=%(dummy_fmri)s "
"%(pfx)s.file=python "
@@ -230,7 +230,7 @@
file NOHASH group=sys mode=0600 owner=root path=var/log/authlog variant.foo=baz variant.num=two
"""
- two_v_deps_output = """\
+ two_v_deps_verbose_output = """\
%(m1_path)s
depend fmri=pkg:/s-v-bar pkg.debug.depend.file=var/log/authlog pkg.debug.depend.file=var/log/file2 pkg.debug.depend.reason=baz pkg.debug.depend.type=hardlink type=require
depend fmri=pkg:/s-v-baz-one pkg.debug.depend.file=var/log/authlog pkg.debug.depend.reason=baz pkg.debug.depend.type=hardlink type=require variant.foo=baz variant.num=one
@@ -251,6 +251,26 @@
"""
+ two_v_deps_output = """\
+%(m1_path)s
+depend fmri=pkg:/s-v-bar type=require
+depend fmri=pkg:/s-v-baz-one type=require variant.foo=baz variant.num=one
+depend fmri=pkg:/s-v-baz-two type=require variant.foo=baz variant.num=two
+
+
+%(m2_path)s
+
+
+
+%(m3_path)s
+
+
+
+%(m4_path)s
+
+
+"""
+
dup_variant_deps = """\
set name=variant.foo value=bar value=baz
set name=variant.num value=one value=two
@@ -390,7 +410,7 @@
Subcommands:
pkgdepend generate [-DIkMm] manifest proto_dir
- pkgdepend [options] resolve [-dMos] manifest ...
+ pkgdepend [options] resolve [-dmosv] manifest ...
Options:
-R dir
@@ -490,7 +510,7 @@
pkg_path +
" %(pfx)s.reason=%(reason)s "
"%(pfx)s.type=python type=require\n"
-
+
"depend fmri=%(dummy_fmri)s "
"%(pfx)s.file=misc.py "
"%(pfx)s.file=misc.pyc "
@@ -499,13 +519,13 @@
pkg_path +
" %(pfx)s.reason=%(reason)s "
"%(pfx)s.type=python type=require\n"
-
+
"depend fmri=%(dummy_fmri)s "
"%(pfx)s.file=pkg/__init__.py " +
self.__make_paths("", vp) +
" %(pfx)s.reason=%(reason)s "
"%(pfx)s.type=python type=require\n"
-
+
"depend fmri=%(dummy_fmri)s "
"%(pfx)s.file=search_storage.py "
"%(pfx)s.file=search_storage.pyc "
@@ -645,13 +665,13 @@
proto=proto, exit=2)
self.pkgdepend_generate("-\?", proto="")
self.pkgdepend_generate("--help", proto="")
-
+
def test_output(self):
"""Check that the output is in the format expected."""
tp = self.make_manifest(self.test_manf_1)
- fp = "usr/lib/python2.6/vendor-packages/pkg/client/indexer.py"
-
+ fp = "usr/lib/python2.6/vendor-packages/pkg/client/indexer.py"
+
self.pkgdepend_generate("%s" % tp,
proto=pkg5unittest.g_proto_area, exit=1)
self.check_res(self.make_res_manf_1(
@@ -671,7 +691,7 @@
self.make_proto_text_file(fp, self.python_text)
self.make_elf([], "usr/xpg4/lib/libcurses.so.1")
-
+
self.pkgdepend_generate("-m %s" % tp, proto=self.test_proto_dir)
self.check_res(
self.make_full_res_manf_1_mod_proto(
@@ -681,7 +701,7 @@
tp = self.make_manifest(self.test_manf_2)
self.make_proto_text_file("etc/pam.conf", "text")
-
+
self.pkgdepend_generate("%s" % tp, proto=self.test_proto_dir)
self.check_res(self.res_manf_2, self.output)
self.check_res("", self.errout)
@@ -696,7 +716,7 @@
base.Dependency.DEPEND_DEBUG_PREFIX,
"dummy_fmri":base.Dependency.DUMMY_FMRI
}, self.errout)
-
+
self.pkgdepend_generate("-M %s" % tp, proto=self.test_proto_dir)
self.check_res(self.res_manf_2, self.output)
self.check_res(self.res_manf_2_missing, self.errout)
@@ -707,7 +727,7 @@
tp = self.make_manifest(self.int_hardlink_manf)
self.make_proto_text_file("var/log/syslog", "text")
-
+
self.pkgdepend_generate("%s" % tp, proto=self.test_proto_dir)
self.check_res("", self.output)
self.check_res("", self.errout)
@@ -734,7 +754,7 @@
3) Does the first line of the file include a specific version
of python.
(Represented by F)
-
+
Conditions || Perform Analysis
X D F || Y, if F and D disagree, display a warning in the
|| output and use D to analyze the file.
@@ -850,7 +870,7 @@
tp = self.make_manifest(
self.pyver_test_manf_1 % {"py_ver":py_ver})
fp = "usr/lib/python%s/vendor-packages/pkg/" \
- "client/indexer.py" % py_ver
+ "client/indexer.py" % py_ver
self.make_proto_text_file(fp, self.python_text)
# Run generate and check the output.
@@ -870,7 +890,7 @@
# Run resolver and check the output.
self.pkgdepend_resolve(
- "%s %s" % (dependency_mp, provider_mp))
+ "-v %s %s" % (dependency_mp, provider_mp))
self.check_res("", self.output)
self.check_res("", self.errout)
dependency_res_p = dependency_mp + ".res"
@@ -893,14 +913,11 @@
def test_resolve_screen_out(self):
"""Check that the results printed to screen are what is
expected."""
-
+
m1_path = self.make_manifest(self.two_variant_deps)
m2_path = self.make_manifest(self.two_v_deps_bar)
m3_path = self.make_manifest(self.two_v_deps_baz_one)
m4_path = self.make_manifest(self.two_v_deps_baz_two)
- p2_name = "s-v-bar"
- p3_name = "s-v-baz-one"
- p4_name = "s-v-baz-two"
self.pkgdepend_resolve("-o %s" %
" ".join([m1_path, m2_path, m3_path, m4_path]), exit=1)
@@ -910,6 +927,7 @@
"m3_path": m3_path,
"m4_path": m4_path
}, self.output)
+
self.check_res(self.two_v_deps_resolve_error % {
"manf_path": m1_path,
"pfx":
@@ -917,6 +935,16 @@
"dummy_fmri":base.Dependency.DUMMY_FMRI
}, self.errout)
+ self.pkgdepend_resolve("-vo %s" %
+ " ".join([m1_path, m2_path, m3_path, m4_path]), exit=1)
+
+ self.check_res(self.two_v_deps_verbose_output % {
+ "m1_path": m1_path,
+ "m2_path": m2_path,
+ "m3_path": m3_path,
+ "m4_path": m4_path
+ }, self.output)
+
def test_bug_10518(self):
""" pkgdepend should exit 2 on input args of the wrong type """
m_path = self.make_manifest(self.test_manf_1)
@@ -970,10 +998,10 @@
m_path = None
nonsense = "This is a nonsense manifest"
m_path = self.make_manifest(nonsense)
-
+
self.pkgdepend_generate("%s" % m_path,
proto=self.test_proto_dir, exit=1)
- self.check_res('pkgdepend: Could not parse manifest ' +
+ self.check_res('pkgdepend: Could not parse manifest ' +
'%s because of the following line:\n' % m_path +
nonsense, self.errout)
@@ -986,7 +1014,7 @@
"""Using the provided run paths, produces a elf binary with
those paths set and checks to make sure that pkgdep run with
the provided arguments performs the substitution correctly."""
-
+
elf_path = self.make_elf(run_paths)
m_path = self.make_manifest(self.elf_sub_manf %
{"file_loc": elf_path})
@@ -1026,7 +1054,7 @@
m_path, proto=self.test_proto_dir)
self.check_res("", self.errout)
self.check_res(self.kernel_manf_stdout_platform, self.output)
-
+
self.debug("Test unexpanded token")
rp = ["/platform/$PLATFORM/foo"]
@@ -1089,7 +1117,7 @@
proto=self.test_proto_dir)
self.check_res("", self.errout)
self.check_res(self.double_double_stdout, self.output)
-
+
def test_bug_12816(self):
"""Test that the error produced by a missing payload action
uses the right path."""
@@ -1141,7 +1169,7 @@
# In the comments below, v.f stands for variant.foo and v.n
# stands for variant.num.
-
+
# dup_variant_deps contains all the dependencies to be resolved.
# It is published as dup-v-deps.
m1_path = self.make_manifest(self.dup_variant_deps)
@@ -1192,10 +1220,7 @@
# that manually added dependencies are propogated correctly.
m8_path = self.make_manifest("\n\n")
- p2_name = "s-v-bar"
- p3_name = "s-v-baz-one"
- p4_name = "s-v-baz-two"
- self.pkgdepend_resolve(" -m %s" % " ".join([m1_path, m2_path,
+ self.pkgdepend_resolve(" -vm %s" % " ".join([m1_path, m2_path,
m3_path, m4_path, m5_path, m6_path, m7_path, m8_path]))
fh = open(m1_path + ".res")
res = fh.read()