99 RootNginxConfig ,
1010 filter_unique ,
1111 get_children_recursive ,
12+ get_parents_recursive ,
1213)
1314
1415
1516def nginx_to_regex (nginx : str ) -> str :
1617 """
17- Convert a nginx-style regex to a python regex
18+ Convert a nginx-style regex to a python regex.
19+ Wildcard files are converted to regexes that match any file in the directory.
1820 """
19- return nginx .replace ("*" , ". *" )
21+ return nginx .replace ("*" , r"[^/] *" )
2022
2123
2224def set_parents_in_include (root_config : RootNginxConfig , block_config : NginxLineConfig ):
@@ -27,6 +29,7 @@ def set_parents_in_include(root_config: RootNginxConfig, block_config: NginxLine
2729 for nested_line_config in nested_file_config .parsed :
2830 nested_line_config .parent = block_config
2931 block_config .children .append (nested_line_config )
32+ set_parents_in_include (root_config , nested_line_config )
3033
3134
3235def set_parents_of_blocks (root_config : RootNginxConfig , line_config : NginxLineConfig ):
@@ -104,44 +107,62 @@ def is_partial_direct_match(
104107 return None
105108
106109
107- def find_matches_in_children (
110+ def get_matching_lines_in_children (
108111 line : NginxLineConfig , filters : List [DirectiveFilter ]
109112) -> Tuple [List [NginxLineConfig ], List [DirectiveFilter ]]:
110113 """
111- Check if the line matches filters. If it matches, return the line,
112- the line's neighbours and all children. If it doesn't match, check
113- if any of the children match the filters. If they do, return all
114- descendants of the line that match the filters, including the current
115- line.
114+ Check if the line matches filters. If it matches, return the line.
115+ If it doesn't match, check if any of the children match the filters.
116116 We also return a list of filters that matched, so we can check if
117117 all filters were matched eventually.
118118 If there are no matches, return an empty list for both the matching
119119 lines and the matched filters.
120120 """
121+ if not filters :
122+ # No filters, meaning that the line matches directly
123+ return [line ], []
124+
125+ logger .debug (f"Checking if line { line } matches filters: { filters } " )
121126 matched_filter = is_partial_direct_match (line , filters )
122127 if matched_filter :
123128 logger .debug (f"Found match in children: { line } " )
124129 all_matched_filters = set ([matched_filter ])
125130 # Search for remaining filters in children, as the parent
126131 # might still be looking for other filters
127- remaining_filters = [f for f in filters if f != matched_filter ]
128132 for child in line .children :
129- _ , child_matched_filters = find_matches_in_children (
130- child , remaining_filters
131- )
132- all_matched_filters .update (child_matched_filters )
133- return [line , * line .neighbours , * get_children_recursive (line )], list (
134- all_matched_filters
135- )
133+ remaining_filters = [f for f in filters if f not in all_matched_filters ]
134+ if remaining_filters :
135+ logger .debug (
136+ f"Looking for remaining filters in child { child } : { remaining_filters } "
137+ )
138+ _ , child_matched_filters = get_matching_lines_in_children (
139+ child , remaining_filters
140+ )
141+ all_matched_filters .update (child_matched_filters )
142+ else :
143+ logger .debug (
144+ f"Found all filters in children of line { line } . We should stop!"
145+ )
146+ break
147+ return [line ], list (all_matched_filters )
136148
137149 # All filters must match at least one child
138150 matched_filters = set ()
139- matches = [line ]
151+ matches = []
140152 for child in line .children :
141- child_matches , child_matched_filters = find_matches_in_children (child , filters )
142- if child_matches :
143- matches .extend (child_matches )
144- matched_filters .update (child_matched_filters )
153+ remaining_filters = [f for f in filters if f not in matched_filters ]
154+ if remaining_filters :
155+ child_matches , child_matched_filters = get_matching_lines_in_children (
156+ child , remaining_filters
157+ )
158+ if child_matches :
159+ matches .extend (child_matches )
160+ matched_filters .update (child_matched_filters )
161+ else :
162+ logger .debug (
163+ f"Found all filters in children of line { line } . We should stop!"
164+ )
165+ break
145166
146167 if len (matched_filters ) == len (filters ):
147168 logger .debug (
@@ -151,6 +172,25 @@ def find_matches_in_children(
151172 return [], []
152173
153174
175+ def expand_upon_direct_match (
176+ match : NginxLineConfig , matched_filters : List [DirectiveFilter ]
177+ ) -> List [NginxLineConfig ]:
178+ """
179+ Expand upon matching lines by recursively looking through
180+ parents and neighbours. However, we don't want to include any
181+ lines that have the same directive as in the filters.
182+ F.e., if the filter looks for location=/banaan, we don't want
183+ to include other recursive location lines.
184+ """
185+ matching_lines = []
186+ for neighbour in match .neighbours :
187+ matching_lines .append (neighbour )
188+ matching_lines .extend (get_children_recursive (neighbour ))
189+ parents = get_parents_recursive (match )
190+ matching_lines .extend (parents )
191+ return matching_lines
192+
193+
154194def filter_config (
155195 lines : Iterator [NginxLineConfig ],
156196 filters : List [DirectiveFilter ],
@@ -160,10 +200,10 @@ def filter_config(
160200 """
161201 matching_lines = []
162202 for line in lines :
163- child_matches , matched_filters = find_matches_in_children (line , filters )
164- if len ( matched_filters ) == len ( filters ):
165- logger . debug ( f"Matched all ( { len ( matched_filters ) } ) filters: { line } " )
166- matching_lines .extend (child_matches )
203+ child_matches , _ = get_matching_lines_in_children (line , filters )
204+ matching_lines . extend ( child_matches )
205+ for match in child_matches :
206+ matching_lines .extend (expand_upon_direct_match ( match , filters ) )
167207
168208 return filter_unique (matching_lines )
169209
0 commit comments