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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use cargo_metadata::{CargoOpt, MetadataCommand, Target};
use log::{debug, info};
use std::{borrow::Cow, env, fs::File, io::Read as _, path::PathBuf};
#[doc(hidden)]
pub mod depinfo;
#[doc(hidden)]
pub mod diagnostic;
#[doc(hidden)]
pub mod input;
#[doc(hidden)]
pub mod links;
#[doc(hidden)]
pub mod output;
#[doc(hidden)]
pub mod preproc;
#[doc(hidden)]
pub mod verify;
use diagnostic::Diagnostic;
use input::{CrateCode, InputFile, TargetType};
#[doc(hidden)]
pub fn read_input(
manifest_path: Option<PathBuf>,
prefer_bin: bool,
expand_macros: bool,
template: PathBuf
) -> (InputFile, Cow<'static, str>, Diagnostic) {
let manifest_path = match manifest_path {
Some(path) if path.is_relative() => Some(env::current_dir().unwrap().join(path)),
Some(path) => Some(path),
None => None
};
let mut cmd = MetadataCommand::new();
cmd.features(CargoOpt::AllFeatures);
if let Some(path) = &manifest_path {
cmd.manifest_path(path);
}
let metadata = cmd.exec().expect("Failed to get cargo metadata");
let pkg = metadata
.root_package()
.expect("Missing root package; did you call this command on a workspace root?");
let is_lib = |target: &&Target| target.is_lib();
let is_default_bin =
|target: &&Target| target.is_bin() && target.name == pkg.name.as_str();
let target_and_type = if prefer_bin {
pkg.targets
.iter()
.find(is_default_bin)
.map(|target| (target, TargetType::Bin))
.or_else(|| {
pkg.targets
.iter()
.find(is_lib)
.map(|target| (target, TargetType::Lib))
})
} else {
pkg.targets
.iter()
.find(is_lib)
.map(|target| (target, TargetType::Lib))
.or_else(|| {
pkg.targets
.iter()
.find(is_default_bin)
.map(|target| (target, TargetType::Bin))
})
};
let (target, target_type) = target_and_type
.or_else(|| {
pkg.targets
.iter()
.find(|target| target.is_bin())
.map(|target| (target, TargetType::Bin))
})
.expect("Failed to find a library or binary target");
let file = target.src_path.as_std_path();
let filename = file
.file_name()
.expect("File has no filename")
.to_string_lossy()
.into_owned();
let code = if expand_macros {
CrateCode::read_expansion(manifest_path.as_ref(), target)
.expect("Failed to read crate code")
} else {
CrateCode::read_from_disk(file).expect("Failed to read crate code")
};
let mut diagnostics = Diagnostic::new(filename, code.0.clone());
let template: Cow<'static, str> = if template.exists() {
let mut buf = String::new();
File::open(template)
.expect("Failed to open template")
.read_to_string(&mut buf)
.expect("Failed to read template");
buf.into()
} else {
include_str!("README.j2").into()
};
info!("Reading {}", file.display());
let input_file =
input::read_code(&metadata, pkg, code, target_type, &mut diagnostics);
debug!("Processing {input_file:#?}");
(input_file, template, diagnostics)
}