1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::path::PathBuf;
pub use cargo_metadata;
pub fn locate_bootloader() -> Result<BootloaderInfo, Error> {
let project_metadata = cargo_metadata::MetadataCommand::new().exec()?;
let kernel_manifest_path = locate_cargo_manifest::locate_manifest()?;
let kernel_pkg = project_metadata
.packages
.iter()
.find(|p| p.manifest_path == kernel_manifest_path)
.ok_or_else(|| Error::KernelPackageNotFound {
manifest_path: kernel_manifest_path.to_owned(),
})?;
let bootloader_pkg = bootloader_package(&project_metadata, kernel_pkg)?;
Ok(BootloaderInfo {
package: bootloader_pkg.to_owned(),
kernel_manifest_path,
})
}
#[derive(Debug)]
pub struct BootloaderInfo {
pub package: cargo_metadata::Package,
pub kernel_manifest_path: PathBuf,
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("An error occured while running `cargo_metadata`")]
CargoMetadata {
#[from]
metadata_error: cargo_metadata::Error,
},
#[error("Failed to locate the cargo manifest (`Cargo.toml`)")]
LocateManifest(#[from] locate_cargo_manifest::LocateManifestError),
#[error(
"Bootloader dependency not found\n\n\
You need to add a dependency on a crate named `bootloader` in your Cargo.toml."
)]
BootloaderNotFound,
#[error(
"Could not find package with manifest path `{manifest_path}` in cargo metadata output"
)]
KernelPackageNotFound {
manifest_path: PathBuf,
},
#[error("Could not find required key `{key}` in cargo metadata output")]
CargoMetadataIncomplete {
key: String,
},
}
fn bootloader_package<'a>(
project_metadata: &'a cargo_metadata::Metadata,
kernel_package: &cargo_metadata::Package,
) -> Result<&'a cargo_metadata::Package, Error> {
let bootloader_name = {
let mut dependencies = kernel_package.dependencies.iter();
let bootloader_package = dependencies
.find(|p| p.rename.as_ref().unwrap_or(&p.name) == "bootloader")
.ok_or(Error::BootloaderNotFound)?;
bootloader_package.name.clone()
};
project_metadata
.packages
.iter()
.find(|p| p.name == bootloader_name)
.ok_or(Error::CargoMetadataIncomplete {
key: format!("packages[name = `{}`", &bootloader_name),
})
}