4
4
5
5
import re
6
6
import os .path
7
+ import json
7
8
8
9
from semmle .path_filters import filter_from_pattern
9
10
from semmle .util import Extractable , PY_EXTENSIONS , isdir , islink , listdir
@@ -30,6 +31,13 @@ def __init__(self, options, modulenames, logger):
30
31
if not os .path .exists (p ) and not options .ignore_missing_modules :
31
32
raise FileNotFoundError ("'%s' does not exist." % p )
32
33
self .paths .add (p )
34
+ # During overlay extraction, only traverse the files that were changed.
35
+ self .overlay_changes = None
36
+ if 'CODEQL_EXTRACTOR_PYTHON_OVERLAY_CHANGES' in os .environ :
37
+ with open (os .environ ['CODEQL_EXTRACTOR_PYTHON_OVERLAY_CHANGES' ], 'r' , encoding = 'utf-8' ) as f :
38
+ data = json .load (f )
39
+ changed_paths = data .get ('changes' , [])
40
+ self .overlay_changes = { os .path .abspath (p ) for p in changed_paths }
33
41
self .exclude_paths = set ([ os .path .abspath (f ) for f in options .exclude_file ])
34
42
self .exclude = exclude_filter_from_options (options )
35
43
self .filter = filter_from_options_and_environment (options )
@@ -48,11 +56,20 @@ def __iter__(self):
48
56
if mod is None :
49
57
self .logger .error ("No module named '%s'." , name )
50
58
raise ExtractorFailure ()
59
+ if self .overlay_changes is not None and mod .path not in self .overlay_changes :
60
+ self .logger .debug ("Skipping module '%s' as it was not changed in overlay extraction." , name )
61
+ continue
51
62
yield mod .get_extractable ()
52
63
for path in self .paths :
64
+ if self .overlay_changes is not None and path not in self .overlay_changes :
65
+ self .logger .debug ("Skipping path '%s' as it was not changed in overlay extraction." , path )
66
+ continue
53
67
yield Extractable .from_path (path )
54
68
for path in self .recurse_files :
55
69
for modpath in self ._treewalk (path ):
70
+ if self .overlay_changes is not None and modpath not in self .overlay_changes :
71
+ self .logger .debug ("Skipping file '%s' as it was not changed in overlay extraction." , modpath )
72
+ continue
56
73
yield Extractable .from_path (modpath )
57
74
for name in self .recurse_packages :
58
75
mod = self .finder .find (name )
@@ -66,6 +83,9 @@ def __iter__(self):
66
83
self .logger .error ("Package '%s' does not have a path." , name )
67
84
raise ExtractorFailure ()
68
85
for modpath in self ._treewalk (path ):
86
+ if self .overlay_changes is not None and modpath not in self .overlay_changes :
87
+ self .logger .debug ("Skipping package '%s' as it was not changed in overlay extraction." , modpath )
88
+ continue
69
89
yield Extractable .from_path (modpath )
70
90
71
91
def _treewalk (self , path ):
0 commit comments