|
17 | 17 | from onlinejudge_verify.languages.models import Language, LanguageEnvironment
|
18 | 18 |
|
19 | 19 | logger = getLogger(__name__)
|
| 20 | +_metadata_by_manifest_path: Dict[pathlib.Path, Dict[str, Any]] = {} |
20 | 21 | _cargo_checked_workspaces: Set[pathlib.Path] = set()
|
21 | 22 | _related_source_files_by_workspace: Dict[pathlib.Path, Dict[pathlib.Path, FrozenSet[pathlib.Path]]] = {}
|
22 | 23 |
|
@@ -300,29 +301,45 @@ def list_environments(self, path: pathlib.Path, *, basedir: pathlib.Path) -> Seq
|
300 | 301 |
|
301 | 302 |
|
302 | 303 | def _cargo_metadata(cwd: pathlib.Path) -> Dict[str, Any]:
|
303 |
| - """Runs `cargo metadata` for a Cargo.toml file in `cwd` or its parent directories. |
| 304 | + """Returns "metadata" for a Cargo.toml file in `cwd` or its parent directories. |
304 | 305 |
|
305 | 306 | :raises ValueError: if `cwd` is not absolute or contains `..`
|
| 307 | + :returns: Output of `cargo metadata` command |
306 | 308 | """
|
307 | 309 | if not cwd.is_absolute() or '..' in cwd.parts:
|
308 | 310 | raise ValueError(f'the `cwd` parameter must be absolute and must not contain `..`: {cwd}')
|
309 | 311 |
|
310 |
| - def find_root_manifest_for_wd() -> pathlib.Path: |
311 |
| - # https://docs.rs/cargo/0.48.0/cargo/util/important_paths/fn.find_root_manifest_for_wd.html |
312 |
| - for directory in [cwd, *cwd.parents]: |
313 |
| - manifest_path = directory / 'Cargo.toml' |
314 |
| - if manifest_path.exists(): |
315 |
| - return manifest_path |
316 |
| - raise RuntimeError(f'Could not find `Cargo.toml` in `{cwd}` or any parent directory') |
317 |
| - |
318 |
| - return _cargo_metadata_by_manifest_path(find_root_manifest_for_wd()) |
| 312 | + # https://docs.rs/cargo/0.49.0/src/cargo/util/important_paths.rs.html#6-20 |
| 313 | + for directory in [cwd, *cwd.parents]: |
| 314 | + manifest_path = directory / 'Cargo.toml' |
| 315 | + if manifest_path.exists(): |
| 316 | + return _cargo_metadata_by_manifest_path(manifest_path) |
| 317 | + raise RuntimeError(f'could not find `Cargo.toml` in `{cwd}` or any parent directory') |
319 | 318 |
|
320 | 319 |
|
321 |
| -@functools.lru_cache(maxsize=None) |
322 | 320 | def _cargo_metadata_by_manifest_path(manifest_path: pathlib.Path) -> Dict[str, Any]:
|
| 321 | + """Returns "metadata" for a certain `Cargo.toml`. |
| 322 | +
|
| 323 | + :returns: Output of `cargo metadata` command |
| 324 | + """ |
| 325 | + if manifest_path in _metadata_by_manifest_path: |
| 326 | + return _metadata_by_manifest_path[manifest_path] |
| 327 | + |
| 328 | + metadata = _run_cargo_metadata(manifest_path) |
| 329 | + root_manifest_path = pathlib.Path(metadata['workspace_root'], 'Cargo.toml') |
| 330 | + if root_manifest_path != manifest_path: |
| 331 | + metadata = _run_cargo_metadata(root_manifest_path) |
| 332 | + |
| 333 | + for key in [root_manifest_path, *(pathlib.Path(p['manifest_path']) for p in metadata['packages'] if p['id'] in metadata['workspace_members'])]: |
| 334 | + _metadata_by_manifest_path[key] = metadata |
| 335 | + |
| 336 | + return metadata |
| 337 | + |
| 338 | + |
| 339 | +def _run_cargo_metadata(manifest_path: pathlib.Path) -> Dict[str, Any]: |
323 | 340 | """Runs `cargo metadata` for a certain `Cargo.toml`.
|
324 | 341 |
|
325 |
| - This function is considered to be executed for every Cargo.toml in the repository. |
| 342 | + This function is considered to be executed just once for every Cargo.toml in the repository. |
326 | 343 | For detailed information about `cargo metadata`, see:
|
327 | 344 |
|
328 | 345 | - <https://doc.rust-lang.org/cargo/commands/cargo-metadata.html#output-format>
|
|
0 commit comments