@@ -67,102 +67,105 @@ pub(crate) fn analyze_graph(
67
67
. into ( ) ,
68
68
) ?;
69
69
70
- // Create a cache for resolved globs.
71
- let glob_resolver = Arc :: new ( Mutex :: new ( GlobResolver :: default ( ) ) ) ;
72
-
73
- // Collect and resolve the imports for each file.
74
- let result = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
75
- let inner_result = Arc :: clone ( & result) ;
76
-
77
- rayon:: scope ( move |scope| {
78
- for resolved_file in paths {
79
- let Ok ( resolved_file) = resolved_file else {
80
- continue ;
81
- } ;
70
+ let imports = {
71
+ // Create a cache for resolved globs.
72
+ let glob_resolver = Arc :: new ( Mutex :: new ( GlobResolver :: default ( ) ) ) ;
73
+
74
+ // Collect and resolve the imports for each file.
75
+ let result = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
76
+ let inner_result = Arc :: clone ( & result) ;
77
+ let db = db. snapshot ( ) ;
78
+
79
+ rayon:: scope ( move |scope| {
80
+ for resolved_file in paths {
81
+ let Ok ( resolved_file) = resolved_file else {
82
+ continue ;
83
+ } ;
84
+
85
+ let path = resolved_file. path ( ) ;
86
+ let package = path
87
+ . parent ( )
88
+ . and_then ( |parent| package_roots. get ( parent) )
89
+ . and_then ( Clone :: clone) ;
90
+
91
+ // Resolve the per-file settings.
92
+ let settings = resolver. resolve ( path) ;
93
+ let string_imports = settings. analyze . detect_string_imports ;
94
+ let include_dependencies = settings. analyze . include_dependencies . get ( path) . cloned ( ) ;
95
+
96
+ // Skip excluded files.
97
+ if ( settings. file_resolver . force_exclude || !resolved_file. is_root ( ) )
98
+ && match_exclusion (
99
+ resolved_file. path ( ) ,
100
+ resolved_file. file_name ( ) ,
101
+ & settings. analyze . exclude ,
102
+ )
103
+ {
104
+ continue ;
105
+ }
82
106
83
- let path = resolved_file. path ( ) ;
84
- let package = path
85
- . parent ( )
86
- . and_then ( |parent| package_roots. get ( parent) )
87
- . and_then ( Clone :: clone) ;
88
-
89
- // Resolve the per-file settings.
90
- let settings = resolver. resolve ( path) ;
91
- let string_imports = settings. analyze . detect_string_imports ;
92
- let include_dependencies = settings. analyze . include_dependencies . get ( path) . cloned ( ) ;
93
-
94
- // Skip excluded files.
95
- if ( settings. file_resolver . force_exclude || !resolved_file. is_root ( ) )
96
- && match_exclusion (
97
- resolved_file. path ( ) ,
98
- resolved_file. file_name ( ) ,
99
- & settings. analyze . exclude ,
100
- )
101
- {
102
- continue ;
103
- }
107
+ // Ignore non-Python files.
108
+ let source_type = match settings. analyze . extension . get ( path) {
109
+ None => match SourceType :: from ( & path) {
110
+ SourceType :: Python ( source_type) => source_type,
111
+ SourceType :: Toml ( _) => {
112
+ debug ! ( "Ignoring TOML file: {}" , path. display( ) ) ;
113
+ continue ;
114
+ }
115
+ } ,
116
+ Some ( language) => PySourceType :: from ( language) ,
117
+ } ;
118
+ if matches ! ( source_type, PySourceType :: Ipynb ) {
119
+ debug ! ( "Ignoring Jupyter notebook: {}" , path. display( ) ) ;
120
+ continue ;
121
+ }
104
122
105
- // Ignore non-Python files.
106
- let source_type = match settings. analyze . extension . get ( path) {
107
- None => match SourceType :: from ( & path) {
108
- SourceType :: Python ( source_type) => source_type,
109
- SourceType :: Toml ( _) => {
110
- debug ! ( "Ignoring TOML file: {}" , path. display( ) ) ;
111
- continue ;
123
+ // Convert to system paths.
124
+ let Ok ( package) = package. map ( SystemPathBuf :: from_path_buf) . transpose ( ) else {
125
+ warn ! ( "Failed to convert package to system path" ) ;
126
+ continue ;
127
+ } ;
128
+ let Ok ( path) = SystemPathBuf :: from_path_buf ( resolved_file. into_path ( ) ) else {
129
+ warn ! ( "Failed to convert path to system path" ) ;
130
+ continue ;
131
+ } ;
132
+
133
+ let db = db. snapshot ( ) ;
134
+ let glob_resolver = glob_resolver. clone ( ) ;
135
+ let root = root. clone ( ) ;
136
+ let result = inner_result. clone ( ) ;
137
+ scope. spawn ( move |_| {
138
+ // Identify any imports via static analysis.
139
+ let mut imports =
140
+ ModuleImports :: detect ( & db, & path, package. as_deref ( ) , string_imports)
141
+ . unwrap_or_else ( |err| {
142
+ warn ! ( "Failed to generate import map for {path}: {err}" ) ;
143
+ ModuleImports :: default ( )
144
+ } ) ;
145
+
146
+ debug ! ( "Discovered {} imports for {}" , imports. len( ) , path) ;
147
+
148
+ // Append any imports that were statically defined in the configuration.
149
+ if let Some ( ( root, globs) ) = include_dependencies {
150
+ let mut glob_resolver = glob_resolver. lock ( ) . unwrap ( ) ;
151
+ imports. extend ( glob_resolver. resolve ( root, globs) ) ;
112
152
}
113
- } ,
114
- Some ( language) => PySourceType :: from ( language) ,
115
- } ;
116
- if matches ! ( source_type, PySourceType :: Ipynb ) {
117
- debug ! ( "Ignoring Jupyter notebook: {}" , path. display( ) ) ;
118
- continue ;
119
- }
120
-
121
- // Convert to system paths.
122
- let Ok ( package) = package. map ( SystemPathBuf :: from_path_buf) . transpose ( ) else {
123
- warn ! ( "Failed to convert package to system path" ) ;
124
- continue ;
125
- } ;
126
- let Ok ( path) = SystemPathBuf :: from_path_buf ( resolved_file. into_path ( ) ) else {
127
- warn ! ( "Failed to convert path to system path" ) ;
128
- continue ;
129
- } ;
130
153
131
- let db = db. snapshot ( ) ;
132
- let glob_resolver = glob_resolver. clone ( ) ;
133
- let root = root. clone ( ) ;
134
- let result = inner_result. clone ( ) ;
135
- scope. spawn ( move |_| {
136
- // Identify any imports via static analysis.
137
- let mut imports =
138
- ModuleImports :: detect ( & db, & path, package. as_deref ( ) , string_imports)
139
- . unwrap_or_else ( |err| {
140
- warn ! ( "Failed to generate import map for {path}: {err}" ) ;
141
- ModuleImports :: default ( )
142
- } ) ;
143
-
144
- debug ! ( "Discovered {} imports for {}" , imports. len( ) , path) ;
145
-
146
- // Append any imports that were statically defined in the configuration.
147
- if let Some ( ( root, globs) ) = include_dependencies {
148
- let mut glob_resolver = glob_resolver. lock ( ) . unwrap ( ) ;
149
- imports. extend ( glob_resolver. resolve ( root, globs) ) ;
150
- }
154
+ // Convert the path (and imports) to be relative to the working directory.
155
+ let path = path
156
+ . strip_prefix ( & root)
157
+ . map ( SystemPath :: to_path_buf)
158
+ . unwrap_or ( path) ;
159
+ let imports = imports. relative_to ( & root) ;
151
160
152
- // Convert the path (and imports) to be relative to the working directory.
153
- let path = path
154
- . strip_prefix ( & root)
155
- . map ( SystemPath :: to_path_buf)
156
- . unwrap_or ( path) ;
157
- let imports = imports. relative_to ( & root) ;
158
-
159
- result. lock ( ) . unwrap ( ) . push ( ( path, imports) ) ;
160
- } ) ;
161
- }
162
- } ) ;
161
+ result. lock ( ) . unwrap ( ) . push ( ( path, imports) ) ;
162
+ } ) ;
163
+ }
164
+ } ) ;
163
165
164
- // Collect the results.
165
- let imports = Arc :: into_inner ( result) . unwrap ( ) . into_inner ( ) ?;
166
+ // Collect the results.
167
+ Arc :: into_inner ( result) . unwrap ( ) . into_inner ( ) ?
168
+ } ;
166
169
167
170
// Generate the import map.
168
171
let import_map = match args. direction {
@@ -173,6 +176,8 @@ pub(crate) fn analyze_graph(
173
176
// Print to JSON.
174
177
println ! ( "{}" , serde_json:: to_string_pretty( & import_map) ?) ;
175
178
179
+ std:: mem:: forget ( db) ;
180
+
176
181
Ok ( ExitStatus :: Success )
177
182
}
178
183
0 commit comments