Repository: ros-infrastructure/rosdep

Issue:
Apply --ignore-src to keys as well
I was recently surprised to learn that `-i`/`--ignore-packages-from-source`/`--ignore-src` only affects `check` and `install`, not `keys` (no error though, of course). That requires one to do their own filtering using e.g. `rospack list-names`, when the functionality obviously already exists in rosdep. How do the maintainers feel about supporting `-i` for `keys` as well, to filter out dependencies already satisfied by packages in the workspace? Happy to do the work.

Discussion:
codecov-io: # [Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=h1) Report
> Merging [#686](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=desc) into [master](https://codecov.io/gh/ros-infrastructure/rosdep/commit/6a7112a2c896bfd5c3e738e1d1fdca98847d8205?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686/graphs/tree.svg?width=650&token=YdnUPit6vO&height=150&src=pr)](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #686      +/-   ##
==========================================
+ Coverage   75.46%   75.47%   +<.01%     
==========================================
  Files          32       32              
  Lines        2967     2968       +1     
==========================================
+ Hits         2239     2240       +1     
  Misses        728      728
```


| [Impacted Files](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/rosdep2/main.py](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686/diff?src=pr&el=tree#diff-c3JjL3Jvc2RlcDIvbWFpbi5weQ==) | `48.58% <100%> (+0.09%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=footer). Last update [6a7112a...e9b3a56](https://codecov.io/gh/ros-infrastructure/rosdep/pull/686?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

kyrofa: @nuclearsandwich curious to get your thoughts on this.

Patch:
diff --git a/src/rosdep2/main.py b/src/rosdep2/main.py
index 585ad8b..50a0bb4 100644
--- a/src/rosdep2/main.py
+++ b/src/rosdep2/main.py
@@ -61,7 +61,7 @@ from . import __version__
 from .core import RosdepInternalError, InstallFailed, UnsupportedOs, InvalidData, CachePermissionError, DownloadFailure
 from .installers import normalize_uninstalled_to_list
 from .installers import RosdepInstaller
-from .lookup import RosdepLookup, ResolutionError
+from .lookup import RosdepLookup, ResolutionError, prune_catkin_packages
 from .rospkg_loader import DEFAULT_VIEW_KEY
 from .sources_list import update_sources_list, get_sources_cache_dir,\
     download_default_sources_list, SourcesListLoader, CACHE_INDEX,\
@@ -292,10 +292,10 @@ def _rosdep_main(args):
                       action='store_false', help="Do not consider implicit/recursive dependencies.  Only valid with 'keys', 'check', and 'install' commands.")
     parser.add_option('--ignore-packages-from-source', '--ignore-src', '-i',
                       dest='ignore_src', default=False, action='store_true',
-                      help="Affects the 'check' and 'install' verbs. If "
-                           'specified then rosdep will not install keys '
-                           'that are found to be catkin packages anywhere in '
-                           'the ROS_PACKAGE_PATH or in any of the directories '
+                      help="Affects the 'check', 'install', and 'keys' verbs. "
+                           'If specified then rosdep will ignore keys that '
+                           'are found to be catkin packages anywhere in the '
+                           'ROS_PACKAGE_PATH or in any of the directories '
                            'given by the --from-paths option.')
     parser.add_option('--skip-keys',
                       dest='skip_keys', action='append', default=[],
@@ -462,7 +462,7 @@ def _package_args_handler(command, parser, options, args):
         raise rospkg.ResourceNotFound(not_found[0], rospack.get_ros_paths())
 
     # Handle the --ignore-src option
-    if command in ['install', 'check'] and options.ignore_src:
+    if command in ['install', 'check', 'keys'] and options.ignore_src:
         if options.verbose:
             print('Searching ROS_PACKAGE_PATH for '
                   'sources: ' + str(os.environ['ROS_PACKAGE_PATH'].split(':')))
@@ -617,16 +617,17 @@ def command_update(options):
 def command_keys(lookup, packages, options):
     lookup = _get_default_RosdepLookup(options)
     rosdep_keys = get_keys(lookup, packages, options.recursive)
+    prune_catkin_packages(rosdep_keys, options.verbose)
     _print_lookup_errors(lookup)
     print('\n'.join(rosdep_keys))
 
 
 def get_keys(lookup, packages, recursive):
-    rosdep_keys = []
+    rosdep_keys = set()  # using a set to ensure uniqueness
     for package_name in packages:
         deps = lookup.get_rosdeps(package_name, implicit=recursive)
-        rosdep_keys.extend(deps)
-    return set(rosdep_keys)
+        rosdep_keys.update(deps)
+    return list(rosdep_keys)
 
 
 def command_check(lookup, packages, options):


Test patch:
diff --git a/test/test_rosdep_main.py b/test/test_rosdep_main.py
index 8c6a595..cc33f1d 100644
--- a/test/test_rosdep_main.py
+++ b/test/test_rosdep_main.py
@@ -256,6 +256,10 @@ class TestRosdepMain(unittest.TestCase):
                 rosdep_main(['keys', 'rospack_fake', '--os', 'ubuntu:lucid', '--verbose'] + cmd_extras)
                 stdout, stderr = b
                 assert stdout.getvalue().strip() == 'testtinyxml', stdout.getvalue()
+            with fakeout() as b:
+                rosdep_main(['keys', 'another_catkin_package'] + cmd_extras + ['-i'])
+                stdout, stderr = b
+                assert stdout.getvalue().strip() == 'catkin', stdout.getvalue()
         except SystemExit:
             assert False, 'system exit occurred'
         try: