66from leapp .logger import configure_logger
77from leapp .repository .scan import find_and_scan_repositories
88from leapp .snactor .context import with_snactor_context
9- from leapp .utils .clicmd import command , command_arg
9+ from leapp .utils .clicmd import command , command_arg , command_opt
1010from leapp .utils .repository import find_repository_basedir , requires_repository
1111
1212_LONG_DESCRIPTION = '''
1919 help = 'Print dependency graph of a workflow in the DOT language.' ,
2020 description = _LONG_DESCRIPTION )
2121@command_arg ('workflow_name' )
22+ @command_opt ('only-influencing-actor' ,
23+ metavar = 'ActorName' ,
24+ help = 'Show only actors that influence the given actor by producing messages' )
2225@requires_repository
2326@with_snactor_context
2427def cli (params ):
@@ -35,6 +38,12 @@ def cli(params):
3538 if not workflow :
3639 raise CommandError ('Could not find any workflow named "{}"' .format (params .name ))
3740
41+ actor_of_interest = None
42+ if params .only_influencing_actor :
43+ actor_of_interest = repository .lookup_actor (params .only_influencing_actor )
44+ if not actor_of_interest :
45+ raise CommandError ('Could not find any workflow named "{}"' .format (params .name ))
46+
3847 workflow_instance = workflow ()
3948
4049 # Information about message consuments and producers:
@@ -50,12 +59,34 @@ def cli(params):
5059 for produced_message in actor .produces :
5160 dependency_graph [produced_message .__name__ ]['producers' ].add (actor .name )
5261
62+ actors_to_include = set ()
63+ if actor_of_interest :
64+ # Compute backwards reachability
65+ worklist = [actor_of_interest .name ]
66+ while worklist :
67+ explored_actor = worklist .pop (- 1 )
68+ actors_to_include .add (explored_actor .name )
69+
70+ for consumed_message in explored_actor .consumes :
71+ message_producer_names = dependency_graph [consumed_message .__name__ ]['producers' ]
72+ for producer_name in message_producer_names :
73+ if producer_name in actors_to_include :
74+ continue
75+
76+ producer = repository .lookup_actor (producer_name )
77+ worklist .append (producer )
78+
5379 # Display the dependency graph in the DOT format. We don't want to add dependencies on another library,
5480 # so we do the formatting ourselves since its pretty straightforward
5581 dot_output_lines = ['digraph LeappDependencyGraph {' ]
5682
5783 for message , message_info in dependency_graph .items ():
5884 for producent , consument in itertools .product (message_info ['producers' ], message_info ['consumers' ]):
85+ # In case we show only influential actors, check that both message source and message targets
86+ # are to be displayed
87+ if actor_of_interest and not actors_to_include .issubset ((producent , consument )):
88+ continue
89+
5990 output_line = ' "{0}" -> "{1}" [label="{2}"]' .format (producent , consument , message )
6091 dot_output_lines .append (output_line )
6192
0 commit comments