Skip to main content

flowey_lib_common/
download_mdbook.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Download a copy of `mdbook`
5
6use flowey::node::prelude::*;
7
8flowey_config! {
9    /// Config for the download_mdbook node.
10    pub struct Config {
11        /// Version of `mdbook` to install
12        pub version: Option<String>,
13    }
14}
15
16flowey_request! {
17    pub enum Request {
18        /// Get a path to `mdbook`
19        GetMdbook(WriteVar<PathBuf>),
20    }
21}
22
23new_flow_node_with_config!(struct Node);
24
25impl FlowNodeWithConfig for Node {
26    type Request = Request;
27    type Config = Config;
28
29    fn imports(ctx: &mut ImportCtx<'_>) {
30        ctx.import::<crate::install_dist_pkg::Node>();
31        ctx.import::<crate::download_gh_release::Node>();
32    }
33
34    fn emit(
35        config: Config,
36        requests: Vec<Self::Request>,
37        ctx: &mut NodeCtx<'_>,
38    ) -> anyhow::Result<()> {
39        let (version, get_mdbook) =
40            collect_download_requests(config.version, requests, |Request::GetMdbook(v)| v)?;
41
42        if get_mdbook.is_empty() {
43            return Ok(());
44        }
45
46        download_mdbook_tool(ctx, "mdbook", "rust-lang", "mdBook", &version, get_mdbook)
47    }
48}
49
50pub(crate) fn collect_download_requests<T>(
51    version: Option<String>,
52    requests: Vec<T>,
53    get_path: impl FnMut(T) -> WriteVar<PathBuf>,
54) -> anyhow::Result<(String, Vec<WriteVar<PathBuf>>)> {
55    let version = version.ok_or(anyhow::anyhow!("missing config: version"))?;
56    let paths = requests.into_iter().map(get_path).collect();
57    Ok((version, paths))
58}
59
60pub(crate) fn download_mdbook_tool(
61    ctx: &mut NodeCtx<'_>,
62    name: &str,
63    repo_owner: &str,
64    repo_name: &str,
65    version: &str,
66    paths: Vec<WriteVar<PathBuf>>,
67) -> anyhow::Result<()> {
68    let binary = ctx.platform().binary(name);
69    let tag = format!("v{version}");
70    let file_name = format!(
71        "{name}-v{version}-x86_64-{}",
72        match ctx.platform() {
73            FlowPlatform::Windows => "pc-windows-msvc.zip",
74            FlowPlatform::Linux(_) => "unknown-linux-gnu.tar.gz",
75            FlowPlatform::MacOs => "apple-darwin.tar.gz",
76            platform => anyhow::bail!("unsupported platform {platform}"),
77        }
78    );
79
80    let archive = ctx.reqv(|v| crate::download_gh_release::Request {
81        repo_owner: repo_owner.into(),
82        repo_name: repo_name.into(),
83        needs_auth: false,
84        tag: tag.clone(),
85        file_name,
86        path: v,
87    });
88
89    let extract_zip_deps = crate::_util::extract::extract_zip_if_new_deps(ctx);
90    ctx.emit_rust_step(format!("unpack {name}"), |ctx| {
91        let extract_zip_deps = extract_zip_deps.claim(ctx);
92        let paths = paths.claim(ctx);
93        let archive = archive.claim(ctx);
94        move |rt| {
95            let archive = rt.read(archive);
96
97            let extract_dir =
98                crate::_util::extract::extract_zip_if_new(rt, extract_zip_deps, &archive, &tag)?;
99
100            rt.write_all(paths, &extract_dir.join(binary));
101
102            Ok(())
103        }
104    });
105    Ok(())
106}