@@ -6,7 +6,7 @@ use crate::lib::canister_info::CanisterInfo;
6
6
use crate :: lib:: environment:: Environment ;
7
7
use crate :: lib:: error:: { BuildError , DfxError , DfxResult } ;
8
8
use crate :: lib:: metadata:: names:: { CANDID_ARGS , CANDID_SERVICE } ;
9
- use crate :: lib:: models:: canister:: CanisterPool ;
9
+ use crate :: lib:: models:: canister:: { CanisterPool , ImportsTracker , MotokoImport } ;
10
10
use crate :: lib:: package_arguments:: { self , PackageArguments } ;
11
11
use crate :: util:: assets:: management_idl;
12
12
use crate :: lib:: builders:: bail;
@@ -17,9 +17,8 @@ use dfx_core::config::model::dfinity::{MetadataVisibility, Profile};
17
17
use dfx_core:: fs:: metadata;
18
18
use fn_error_context:: context;
19
19
use slog:: { info, o, trace, warn, Logger } ;
20
- use std:: collections:: { BTreeMap , BTreeSet } ;
20
+ use std:: collections:: BTreeMap ;
21
21
use std:: convert:: TryFrom ;
22
- use std:: fmt:: Debug ;
23
22
use std:: path:: { Path , PathBuf } ;
24
23
use std:: process:: Output ;
25
24
use std:: sync:: Arc ;
@@ -43,20 +42,19 @@ impl MotokoBuilder {
43
42
}
44
43
}
45
44
45
+ // TODO: Rename this function.
46
46
#[ context( "Failed to find imports for canister at '{}'." , info. get_main_path( ) . display( ) ) ]
47
- fn get_imports ( cache : & dyn Cache , info : & MotokoCanisterInfo ) -> DfxResult < BTreeSet < MotokoImport > > {
48
- #[ context( "Failed recursive dependency detection at {}." , file. display( ) ) ]
49
- fn get_imports_recursive (
47
+ fn get_imports ( cache : & dyn Cache , info : & MotokoCanisterInfo , imports : & mut ImportsTracker ) -> DfxResult < ( ) > {
48
+ #[ context( "Failed recursive dependency detection at {}." , file. display( ) ) ] // FIXME
49
+ fn get_imports_recursive (
50
50
cache : & dyn Cache ,
51
51
file : & Path ,
52
- result : & mut BTreeSet < MotokoImport > ,
52
+ imports : & mut ImportsTracker ,
53
53
) -> DfxResult {
54
- if result . contains ( & MotokoImport :: Relative ( file. to_path_buf ( ) ) ) {
54
+ if imports . nodes . contains_key ( & MotokoImport :: Relative ( file. to_path_buf ( ) ) ) {
55
55
return Ok ( ( ) ) ;
56
56
}
57
57
58
- result. insert ( MotokoImport :: Relative ( file. to_path_buf ( ) ) ) ;
59
-
60
58
let mut command = cache. get_binary_command ( "moc" ) ?;
61
59
let command = command. arg ( "--print-deps" ) . arg ( file) ;
62
60
let output = command
@@ -68,21 +66,25 @@ fn get_imports(cache: &dyn Cache, info: &MotokoCanisterInfo) -> DfxResult<BTreeS
68
66
let import = MotokoImport :: try_from ( line) . context ( "Failed to create MotokoImport." ) ?;
69
67
match import {
70
68
MotokoImport :: Relative ( path) => {
71
- get_imports_recursive ( cache, path. as_path ( ) , result ) ?;
69
+ get_imports_recursive ( cache, path. as_path ( ) , imports ) ?;
72
70
}
73
71
_ => {
74
- result. insert ( import) ;
72
+ let parent = MotokoImport :: Relative ( file. to_path_buf ( ) ) ;
73
+ // imports.insert(parent);
74
+
75
+ let parent_node = imports. graph . add_node ( parent) ;
76
+ let child_node = imports. graph . add_node ( import) ;
77
+ imports. graph . add_edge ( parent_node, child_node, ( ) ) ;
75
78
}
76
79
}
77
80
}
78
81
79
82
Ok ( ( ) )
80
83
}
81
84
82
- let mut result = BTreeSet :: new ( ) ;
83
- get_imports_recursive ( cache, info. get_main_path ( ) , & mut result) ?;
85
+ get_imports_recursive ( cache, info. get_main_path ( ) , imports) ?;
84
86
85
- Ok ( result )
87
+ Ok ( ( ) )
86
88
}
87
89
88
90
impl CanisterBuilder for MotokoBuilder {
@@ -93,13 +95,13 @@ impl CanisterBuilder for MotokoBuilder {
93
95
info : & CanisterInfo ,
94
96
) -> DfxResult < Vec < CanisterId > > {
95
97
let motoko_info = info. as_info :: < MotokoCanisterInfo > ( ) ?;
96
- let imports = get_imports ( self . cache . as_ref ( ) , & motoko_info) ?; // TODO: slow operation
98
+ get_imports ( self . cache . as_ref ( ) , & motoko_info, & mut * pool . imports . borrow_mut ( ) ) ?; // TODO: slow operation
97
99
98
- Ok ( imports
100
+ Ok ( pool . imports . borrow_mut ( ) . nodes
99
101
. iter ( )
100
102
. filter_map ( |import| {
101
- if let MotokoImport :: Canister ( name) = import {
102
- pool. get_first_canister_with_name ( name)
103
+ if let MotokoImport :: Canister ( name) = import. 0 {
104
+ pool. get_first_canister_with_name ( name. as_str ( ) )
103
105
} else {
104
106
None
105
107
}
@@ -144,10 +146,10 @@ impl CanisterBuilder for MotokoBuilder {
144
146
std:: fs:: create_dir_all ( idl_dir_path)
145
147
. with_context ( || format ! ( "Failed to create {}." , idl_dir_path. to_string_lossy( ) ) ) ?;
146
148
147
- let imports = get_imports ( cache. as_ref ( ) , & motoko_info) ?; // TODO: repeated slow operation
149
+ get_imports ( cache. as_ref ( ) , & motoko_info, & mut * pool . imports . borrow_mut ( ) ) ?; // TODO: repeated slow operation
148
150
149
151
// If the management canister is being imported, emit the candid file.
150
- if imports. contains ( & MotokoImport :: Ic ( "aaaaa-aa" . to_string ( ) ) )
152
+ if pool . imports . borrow ( ) . nodes . contains_key ( & MotokoImport :: Ic ( "aaaaa-aa" . to_string ( ) ) )
151
153
{
152
154
let management_idl_path = idl_dir_path. join ( "aaaaa-aa.did" ) ;
153
155
dfx_core:: fs:: write ( management_idl_path, management_idl ( ) ?) ?;
@@ -171,12 +173,13 @@ impl CanisterBuilder for MotokoBuilder {
171
173
// Check that one of the dependencies is newer than the target:
172
174
if let Ok ( wasm_file_metadata) = metadata ( output_wasm_path) {
173
175
let wasm_file_time = wasm_file_metadata. modified ( ) ?;
174
- let mut import_iter = imports. iter ( ) ;
176
+ let imports = pool. imports . borrow ( ) ;
177
+ let mut import_iter = imports. nodes . iter ( ) ;
175
178
loop {
176
179
if let Some ( import) = import_iter. next ( ) {
177
- let imported_file = match import {
180
+ let imported_file = match import. 0 {
178
181
MotokoImport :: Canister ( canister_name) => {
179
- if let Some ( canister) = pool. get_first_canister_with_name ( canister_name) {
182
+ if let Some ( canister) = pool. get_first_canister_with_name ( canister_name. as_str ( ) ) {
180
183
let main_file = canister. get_info ( ) . get_main_file ( ) ;
181
184
if let Some ( main_file) = main_file {
182
185
Some ( main_file. to_owned ( ) )
@@ -188,7 +191,7 @@ impl CanisterBuilder for MotokoBuilder {
188
191
}
189
192
}
190
193
MotokoImport :: Ic ( canister_id) => {
191
- if let Some ( canister_name) = rev_id_map. get ( canister_id) {
194
+ if let Some ( canister_name) = rev_id_map. get ( canister_id. as_str ( ) ) {
192
195
if let Some ( canister) = pool. get_first_canister_with_name ( canister_name) {
193
196
if let Some ( main_file) = canister. get_info ( ) . get_main_file ( ) {
194
197
Some ( main_file. to_owned ( ) )
@@ -210,7 +213,7 @@ impl CanisterBuilder for MotokoBuilder {
210
213
) ;
211
214
expanded. join ( & path[ i+1 ..] )
212
215
} else {
213
- Path :: new ( path) . to_owned ( )
216
+ Path :: new ( path. as_str ( ) ) . to_owned ( )
214
217
} ;
215
218
let path2 = pre_path. to_string_lossy ( ) + ".mo" ; // TODO: Is `lossy` OK?
216
219
let path2 = path2. to_string ( ) ;
@@ -227,7 +230,7 @@ impl CanisterBuilder for MotokoBuilder {
227
230
}
228
231
}
229
232
MotokoImport :: Relative ( path) => {
230
- Some ( Path :: new ( path) . to_owned ( ) )
233
+ Some ( Path :: new ( & path) . to_owned ( ) )
231
234
}
232
235
} ;
233
236
if let Some ( imported_file) = imported_file {
@@ -364,14 +367,6 @@ fn motoko_compile(logger: &Logger, cache: &dyn Cache, params: &MotokoParams<'_>)
364
367
Ok ( ( ) )
365
368
}
366
369
367
- #[ derive( Debug , PartialOrd , Ord , PartialEq , Eq ) ]
368
- enum MotokoImport {
369
- Canister ( String ) ,
370
- Ic ( String ) ,
371
- Lib ( String ) ,
372
- Relative ( PathBuf ) ,
373
- }
374
-
375
370
impl TryFrom < & str > for MotokoImport {
376
371
type Error = DfxError ;
377
372
0 commit comments