diff --git a/src/install.rs b/src/install.rs index 30bcb0a..4b550ec 100644 --- a/src/install.rs +++ b/src/install.rs @@ -72,74 +72,79 @@ impl<'a> Step<'a> { pub async fn invoke(&self, ctx: &Context) -> Result<()> { match self { Self::DownloadFile { res, file } => { - println!( - "Downloading file {file} from {res:?}...", - file = file.to_str().unwrap_or("") - ); - const FETCH_FILE_ERROR_MSG: &'static str = "Fetching the remote resource failed."; - const WRITE_FILE_ERROR_MSG: &'static str = - "Writing the remote resource to disk failed."; - let url = match res { - RemoteResource::Url(url) => url::Url::parse(url) - .into_diagnostic() - .wrap_err("Invalid url for download step.")?, - RemoteResource::GitHubArtifact { repo, pattern } => { - let mut release = fetch_latest_release(&ctx.reqwest, repo).await?; - let pattern = ramhorns::Template::new(*pattern) + if file.exists() { + println!("File {file} already downloaded."); + } else { + println!( + "Downloading file {file} from {res:?}...", + file = file.to_str().unwrap_or("") + ); + const FETCH_FILE_ERROR_MSG: &'static str = + "Fetching the remote resource failed."; + const WRITE_FILE_ERROR_MSG: &'static str = + "Writing the remote resource to disk failed."; + let url = match res { + RemoteResource::Url(url) => url::Url::parse(url) .into_diagnostic() - .wrap_err("Invalid pattern for artifact matching in download step.")?; - release.meta.tag_name_strip_prefix = release - .meta - .tag_name - .strip_prefix('v') - .unwrap_or(&release.meta.tag_name); - let asset_name = pattern.render(&release.meta); - let artifact = release.assets.into_iter().filter(move |asset| asset.name == asset_name).next().ok_or_else(|| miette!("No artifact of the latest release matched the pattern in download step."))?; - url::Url::parse(&artifact.browser_download_url) - .into_diagnostic() - .wrap_err( - "Invalid url returned by GitHub for latest release artifact.", - )? - } - }; - let mut resp = ctx - .reqwest - .get(url) - .header("User-Agent", USER_AGENT_STR) - .send() - .await - .into_diagnostic() - .wrap_err(FETCH_FILE_ERROR_MSG)?; - let _content_length = resp.content_length(); - mkdir_all( - file.parent().ok_or_else(|| { - miette!("Destination file for download step has no parent.") - })?, - ) - .await?; - let mut writer = tokio::io::BufWriter::new( - tokio::fs::File::create(file.as_os_str()) + .wrap_err("Invalid url for download step.")?, + RemoteResource::GitHubArtifact { repo, pattern } => { + let mut release = fetch_latest_release(&ctx.reqwest, repo).await?; + let pattern = ramhorns::Template::new(*pattern) + .into_diagnostic() + .wrap_err( + "Invalid pattern for artifact matching in download step.", + )?; + release.meta.tag_name_strip_prefix = release + .meta + .tag_name + .strip_prefix('v') + .unwrap_or(&release.meta.tag_name); + let asset_name = pattern.render(&release.meta); + let artifact = release.assets.into_iter().filter(move |asset| asset.name == asset_name).next().ok_or_else(|| miette!("No artifact of the latest release matched the pattern in download step."))?; + url::Url::parse(&artifact.browser_download_url) + .into_diagnostic() + .wrap_err( + "Invalid url returned by GitHub for latest release artifact.", + )? + } + }; + let mut resp = ctx + .reqwest + .get(url) + .header("User-Agent", USER_AGENT_STR) + .send() .await .into_diagnostic() - .wrap_err(WRITE_FILE_ERROR_MSG)?, - ); - while let Some(mut chunk) = resp - .chunk() - .await - .into_diagnostic() - .wrap_err(FETCH_FILE_ERROR_MSG)? - { + .wrap_err(FETCH_FILE_ERROR_MSG)?; + let _content_length = resp.content_length(); + mkdir_all(file.parent().ok_or_else(|| { + miette!("Destination file for download step has no parent.") + })?) + .await?; + let mut writer = tokio::io::BufWriter::new( + tokio::fs::File::create(file.as_os_str()) + .await + .into_diagnostic() + .wrap_err(WRITE_FILE_ERROR_MSG)?, + ); + while let Some(mut chunk) = resp + .chunk() + .await + .into_diagnostic() + .wrap_err(FETCH_FILE_ERROR_MSG)? + { + writer + .write_all_buf(&mut chunk) + .await + .into_diagnostic() + .wrap_err(WRITE_FILE_ERROR_MSG)?; + } writer - .write_all_buf(&mut chunk) + .flush() .await .into_diagnostic() .wrap_err(WRITE_FILE_ERROR_MSG)?; } - writer - .flush() - .await - .into_diagnostic() - .wrap_err(WRITE_FILE_ERROR_MSG)?; } Self::ExtractFile { file, dest } => { const EXTRACT_FILE_ERROR_MSG: &'static str = "Extracting file failed.";