| 84 | } |
| 85 | |
| 86 | fn linearize_tree(tree: &SourceTree) -> Result<Vec<SourceFile<'_>>> { |
| 87 | // find root |
| 88 | let root_path; |
| 89 | |
| 90 | if tree.sources.len() == 1 { |
| 91 | // if there is only one file, use that as the root |
| 92 | root_path = tree.sources.keys().next().unwrap(); |
| 93 | } else if let Some(root) = tree.sources.get_key_value(&PathBuf::from("")) { |
| 94 | // if there is an empty path, that's the root |
| 95 | root_path = root.0; |
| 96 | } else if let Some(root) = tree.sources.keys().find(path_starts_with_uppercase) { |
| 97 | root_path = root; |
| 98 | } else { |
| 99 | if tree.sources.is_empty() { |
| 100 | // TODO: should we allow non `.prql` files? We could require `.prql` |
| 101 | // for modules but then allow any file if a single file is passed |
| 102 | // (python allows this, for example) |
| 103 | return Err(Error::new_simple( |
| 104 | "No `.prql` files found in the source tree", |
| 105 | )); |
| 106 | } |
| 107 | |
| 108 | let file_names = tree |
| 109 | .sources |
| 110 | .keys() |
| 111 | .map(|p| format!(" - {}", p.to_str().unwrap_or_default())) |
| 112 | .sorted() |
| 113 | .join("\n"); |
| 114 | |
| 115 | return Err(Error::new_simple(format!( |
| 116 | "Cannot find the root module within the following files:\n{file_names}" |
| 117 | )) |
| 118 | .push_hint("add a file that starts with uppercase letter to the root directory") |
| 119 | .with_code("E0002")); |
| 120 | } |
| 121 | |
| 122 | let mut sources: Vec<_> = Vec::with_capacity(tree.sources.len()); |
| 123 | |
| 124 | // prepare paths |
| 125 | for (path, source) in &tree.sources { |
| 126 | if path == root_path { |
| 127 | continue; |
| 128 | } |
| 129 | |
| 130 | let module_path = os_path_to_prql_path(path)?; |
| 131 | |
| 132 | sources.push(SourceFile { |
| 133 | file_path: path, |
| 134 | module_path, |
| 135 | content: source, |
| 136 | }); |
| 137 | } |
| 138 | |
| 139 | // sort to make this deterministic |
| 140 | sources.sort_by(|a, b| a.module_path.cmp(&b.module_path)); |
| 141 | |
| 142 | // add root |
| 143 | let root_content = tree.sources.get(root_path).unwrap(); |