]> git.lizzy.rs Git - rust.git/blob - src/tools/build-manifest/src/manifest.rs
Rollup merge of #100522 - cjgillot:inline-polymorphic-recursion, r=tmiasko
[rust.git] / src / tools / build-manifest / src / manifest.rs
1 use crate::Builder;
2 use serde::{Serialize, Serializer};
3 use std::collections::BTreeMap;
4 use std::path::{Path, PathBuf};
5
6 #[derive(Serialize)]
7 #[serde(rename_all = "kebab-case")]
8 pub(crate) struct Manifest {
9     pub(crate) manifest_version: String,
10     pub(crate) date: String,
11     pub(crate) pkg: BTreeMap<String, Package>,
12     pub(crate) artifacts: BTreeMap<String, Artifact>,
13     pub(crate) renames: BTreeMap<String, Rename>,
14     pub(crate) profiles: BTreeMap<String, Vec<String>>,
15 }
16
17 impl Manifest {
18     pub(crate) fn add_artifact(&mut self, name: &str, f: impl FnOnce(&mut Artifact)) {
19         let mut artifact = Artifact { target: BTreeMap::new() };
20         f(&mut artifact);
21         self.artifacts.insert(name.to_string(), artifact);
22     }
23 }
24
25 #[derive(Serialize)]
26 pub(crate) struct Package {
27     pub(crate) version: String,
28     pub(crate) git_commit_hash: Option<String>,
29     pub(crate) target: BTreeMap<String, Target>,
30 }
31
32 #[derive(Serialize)]
33 pub(crate) struct Rename {
34     pub(crate) to: String,
35 }
36
37 #[derive(Serialize)]
38 pub(crate) struct Artifact {
39     pub(crate) target: BTreeMap<String, Vec<ArtifactFile>>,
40 }
41
42 impl Artifact {
43     pub(crate) fn add_file(&mut self, builder: &mut Builder, target: &str, path: &str) {
44         if let Some(path) = record_shipped_file(builder, builder.input.join(path)) {
45             self.target.entry(target.into()).or_insert_with(Vec::new).push(ArtifactFile {
46                 url: builder.url(&path),
47                 hash_sha256: FileHash::Missing(path),
48             });
49         }
50     }
51
52     pub(crate) fn add_tarball(&mut self, builder: &mut Builder, target: &str, base_path: &str) {
53         let files = self.target.entry(target.into()).or_insert_with(Vec::new);
54         let base_path = builder.input.join(base_path);
55         for compression in &["gz", "xz"] {
56             if let Some(tarball) = tarball_variant(builder, &base_path, compression) {
57                 files.push(ArtifactFile {
58                     url: builder.url(&tarball),
59                     hash_sha256: FileHash::Missing(tarball),
60                 });
61             }
62         }
63     }
64 }
65
66 #[derive(Serialize)]
67 #[serde(rename_all = "kebab-case")]
68 pub(crate) struct ArtifactFile {
69     pub(crate) url: String,
70     pub(crate) hash_sha256: FileHash,
71 }
72
73 #[derive(Serialize, Default)]
74 pub(crate) struct Target {
75     pub(crate) available: bool,
76     pub(crate) url: Option<String>,
77     pub(crate) hash: Option<FileHash>,
78     pub(crate) xz_url: Option<String>,
79     pub(crate) xz_hash: Option<FileHash>,
80     pub(crate) components: Option<Vec<Component>>,
81     pub(crate) extensions: Option<Vec<Component>>,
82 }
83
84 impl Target {
85     pub(crate) fn from_compressed_tar(builder: &mut Builder, base_path: &str) -> Self {
86         let base_path = builder.input.join(base_path);
87         let gz = tarball_variant(builder, &base_path, "gz");
88         let xz = tarball_variant(builder, &base_path, "xz");
89
90         if gz.is_none() {
91             return Self::unavailable();
92         }
93
94         Self {
95             available: true,
96             components: None,
97             extensions: None,
98             // .gz
99             url: gz.as_ref().map(|path| builder.url(path)),
100             hash: gz.map(FileHash::Missing),
101             // .xz
102             xz_url: xz.as_ref().map(|path| builder.url(path)),
103             xz_hash: xz.map(FileHash::Missing),
104         }
105     }
106
107     pub(crate) fn unavailable() -> Self {
108         Self::default()
109     }
110 }
111
112 #[derive(Serialize)]
113 pub(crate) struct Component {
114     pub(crate) pkg: String,
115     pub(crate) target: String,
116 }
117
118 impl Component {
119     pub(crate) fn from_str(pkg: &str, target: &str) -> Self {
120         Self { pkg: pkg.to_string(), target: target.to_string() }
121     }
122 }
123
124 #[allow(unused)]
125 pub(crate) enum FileHash {
126     Missing(PathBuf),
127     Present(String),
128 }
129
130 impl Serialize for FileHash {
131     fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
132         match self {
133             FileHash::Missing(path) => Err(serde::ser::Error::custom(format!(
134                 "can't serialize a missing hash for file {}",
135                 path.display()
136             ))),
137             FileHash::Present(inner) => inner.serialize(serializer),
138         }
139     }
140 }
141
142 fn tarball_variant(builder: &mut Builder, base: &Path, ext: &str) -> Option<PathBuf> {
143     let mut path = base.to_path_buf();
144     path.set_extension(ext);
145     record_shipped_file(builder, path)
146 }
147
148 fn record_shipped_file(builder: &mut Builder, path: PathBuf) -> Option<PathBuf> {
149     if path.is_file() {
150         builder.shipped_files.insert(
151             path.file_name()
152                 .expect("missing filename")
153                 .to_str()
154                 .expect("non-utf-8 filename")
155                 .to_string(),
156         );
157         Some(path)
158     } else {
159         None
160     }
161 }
162
163 pub(crate) fn visit_file_hashes(manifest: &mut Manifest, mut f: impl FnMut(&mut FileHash)) {
164     for pkg in manifest.pkg.values_mut() {
165         for target in pkg.target.values_mut() {
166             if let Some(hash) = &mut target.hash {
167                 f(hash);
168             }
169             if let Some(hash) = &mut target.xz_hash {
170                 f(hash);
171             }
172         }
173     }
174
175     for artifact in manifest.artifacts.values_mut() {
176         for target in artifact.target.values_mut() {
177             for file in target {
178                 f(&mut file.hash_sha256);
179             }
180         }
181     }
182 }