Skip to content

Commit

Permalink
list: Clarifying depends and depends-on behavior, adding recursive fu…
Browse files Browse the repository at this point in the history
…nctionality
  • Loading branch information
jbohren committed Feb 13, 2016
1 parent 5608ea8 commit 12872fd
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 44 deletions.
27 changes: 27 additions & 0 deletions catkin_tools/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,33 @@ def get_recursive_build_dependants_in_workspace(package_name, ordered_packages):

return recursive_dependants

def get_recursive_run_dependants_in_workspace(package_name, ordered_packages):
"""Calculates the recursive run dependants of a package which are also in
the ordered_packages
:param package: package for which the recursive depends should be calculated
:type package: :py:class:`catkin_pkg.package.Package`
:param ordered_packages: packages in the workspace, ordered topologically
:type ordered_packages: list(tuple(package path,
:py:class:`catkin_pkg.package.Package`))
:returns: list of package path, package object tuples which are the
recursive run depends for the given package
:rtype: list(tuple(package path, :py:class:`catkin_pkg.package.Package`))
"""
recursive_dependants = list()

for pth, pkg in reversed(ordered_packages):
# Break if this is one to check
if pkg.name == package_name:
break

# Check if this package depends on the target package
deps = get_recursive_run_depends_in_workspace([pkg], ordered_packages)
deps_names = [p.name for _, p in deps]
if package_name in deps_names:
recursive_dependants.insert(0, (pth, pkg))

return recursive_dependants

def is_tty(stream):
"""Returns True if the given stream is a tty, else False"""
Expand Down
8 changes: 4 additions & 4 deletions catkin_tools/verbs/catkin_clean/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ def prepare_arguments(parser):
add = basic_group.add_argument
add('-a', '--all', action='store_true', default=False,
help='Remove all of the generated spaces associated with the given or '
'active profile. This will remove everything but the source space and '
'active profile. This will remove everything except the source space and '
'the hidden .catkin_tools directory.')
add('-b', '--build', action='store_true', default=False,
help='Remove the entire buildspace.')
add('-d', '--devel', action='store_true', default=False,
help='Remove the entire develspace.')
add('-i', '--install', action='store_true', default=False,
help='Remove the entire installspace.')
add('-l', '--logs', action='store_true', default=False,
help='Remove the log directory.')
add('--deinit', action='store_true', default=False,
help='De-initialize the workspace, delete all build profiles and configuration.')

Expand All @@ -106,12 +108,10 @@ def prepare_arguments(parser):
# Advanced group
advanced_group = parser.add_argument_group(
'Advanced',
"Clean only specific parts of the workspace for specified packages. These options will "
"Clean other specific parts of the workspace. These options will "
"automatically enable the --force-cmake option for the next build "
"invocation.")
add = advanced_group.add_argument
add('-l', '--logs', action='store_true', default=False,
help='Only clear the catkin-generated logfiles.')
add('--setup-files', action='store_true', default=False,
help='Clear the catkin-generated setup files from the devel and install spaces.')

Expand Down
122 changes: 82 additions & 40 deletions catkin_tools/verbs/catkin_list/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@

from catkin_tools.context import Context

from catkin_tools.common import get_recursive_build_dependants_in_workspace
from catkin_tools.common import get_recursive_build_depends_in_workspace
from catkin_tools.common import get_recursive_run_dependants_in_workspace
from catkin_tools.common import get_recursive_run_depends_in_workspace

from catkin_pkg.packages import find_packages
from catkin_pkg.package import InvalidPackage
from catkin_pkg.topological_order import topological_order_packages

from catkin_tools.terminal_color import ColorMapper

Expand All @@ -34,13 +40,23 @@ def prepare_arguments(parser):
add_context_args(parser)

add = parser.add_argument
# What packages to build
add('folders', nargs='*',
help='Folders in which to find packages. (default: workspace source space)')
add('--deps', '--dependencies', default=False, action='store_true',
help="List dependencies of each package.")
add('--depends-on', nargs='*',
help="List all packages that depend on supplied argument package(s).")

information_group = parser.add_argument_group('Information', 'Control which information is shown.')
group = information_group.add_mutually_exclusive_group()
group.add_argument('--deps', '--dependencies', default=False, action='store_true',
help="Show direct dependencies of each package.")
group.add_argument('--rdeps', '--recursive-dependencies', default=False, action='store_true',
help="Show recursive dependencies of each package.")

packages_group = parser.add_argument_group('Packages', 'Control which packages are listed.')
add = packages_group.add_argument
add('--depends-on', nargs='*',metavar='PKG',default=[],
help="Only show packages that directly depend on specific package(s).")
add('--rdepends-on','--recursive-depends-on', nargs='*',metavar='PKG',default=[],
help="Only show packages that recursively depend on specific package(s).")

behavior_group = parser.add_argument_group('Interface', 'The behavior of the command-line interface.')
add = behavior_group.add_argument
add('--quiet', default=False, action='store_true',
help="Don't print out detected package warnings.")
add('--unformatted', '-u', default=None, action='store_true',
Expand All @@ -51,46 +67,72 @@ def prepare_arguments(parser):

def main(opts):

if opts.folders:
folders = opts.folders
else:
# Load the context
ctx = Context.load(opts.workspace, opts.profile, load_env=False)
# Load the context
ctx = Context.load(opts.workspace, opts.profile, load_env=False)

if not ctx:
print(clr("@{rf}ERROR: Could not determine workspace.@|"), file=sys.stderr)
sys.exit(1)
if not ctx:
print(clr("@{rf}ERROR: Could not determine workspace.@|"), file=sys.stderr)
sys.exit(1)

folders = [ctx.source_space_abs]
folders = [ctx.source_space_abs]

list_entry_format = '@{pf}-@| @{cf}%s@|' if not opts.unformatted else '%s'

opts.depends_on = set(opts.depends_on) if opts.depends_on else set()
warnings = []
try:
for folder in folders:
for pkg_pth, pkg in find_packages(folder, warnings=warnings).items():
build_depend_names = [d.name for d in pkg.build_depends]
is_build_dep = opts.depends_on.intersection(
build_depend_names)
run_depend_names = [d.name for d in pkg.run_depends]
is_run_dep = opts.depends_on.intersection(
run_depend_names)
if not opts.depends_on or is_build_dep or is_run_dep:
print(clr(list_entry_format % pkg.name))
if opts.deps:
if build_depend_names:
print(clr(' @{yf}build_depend:@|'))
for dep in build_depend_names:
print(clr(' @{pf}-@| %s' % dep))
if run_depend_names:
print(clr(' @{yf}run_depend:@|'))
for dep in run_depend_names:
print(clr(' @{pf}-@| %s' % dep))
except InvalidPackage as ex:
message = '\n'.join(ex.args)
print(clr("@{rf}Error:@| The directory %s contains an invalid package."
" See below for details:\n\n%s" % (folder, message)))
for folder in folders:
try:
packages = find_packages(folder, warnings=warnings)
ordered_packages = topological_order_packages(packages)
packages_by_name = {pkg.name: pkg for pth, pkg in ordered_packages}

if opts.depends_on or opts.rdepends_on:

dependants = set()

for pth, pkg in ordered_packages:
is_dep = opts.depends_on.intersection([
p.name for p in pkg.build_depends + pkg.run_depends])
if is_dep:
dependants.add(pkg.name)

for pkg in [packages_by_name.get(n) for n in opts.rdepends_on]:
if pkg is None:
continue
rbd = get_recursive_build_dependants_in_workspace(pkg.name, ordered_packages)
rrd = get_recursive_run_dependants_in_workspace(pkg.name, ordered_packages)
dependants.update([p.name for _,p in rbd])
dependants.update([p.name for _,p in rrd])

filtered_packages = [
(pth, pkg)
for pth, pkg in ordered_packages
if pkg.name in dependants]
else:
filtered_packages = ordered_packages

for pkg_pth, pkg in filtered_packages:
print(clr(list_entry_format % pkg.name))
if opts.rdeps:
build_deps = [p for dp, p in get_recursive_build_depends_in_workspace(pkg, ordered_packages)]
run_deps = [p for dp, p in get_recursive_run_depends_in_workspace([pkg], ordered_packages)]
else:
build_deps = pkg.build_depends
run_deps = pkg.run_depends

if opts.deps or opts.rdeps:
if len(build_deps) > 0:
print(clr(' @{yf}build_depend:@|'))
for dep in build_deps:
print(clr(' @{pf}-@| %s' % dep.name))
if len(run_deps) > 0:
print(clr(' @{yf}run_depend:@|'))
for dep in run_deps:
print(clr(' @{pf}-@| %s' % dep.name))
except InvalidPackage as ex:
message = '\n'.join(ex.args)
print(clr("@{rf}Error:@| The directory %s contains an invalid package."
" See below for details:\n\n%s" % (folder, message)))

# Print out warnings
if not opts.quiet:
Expand Down

0 comments on commit 12872fd

Please # to comment.