From 283848e35306f3f0f3b70a1378e8c559f1f4f268 Mon Sep 17 00:00:00 2001 From: Matthew James Briggs Date: Thu, 30 Nov 2023 18:07:56 -0800 Subject: [PATCH] deprecate release.toml When loading a project, issue a deprecation warning if Release.toml is found. If it is found, ensure that its version field is aligned with Twoliter.toml --- twoliter/src/project.rs | 100 ++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 13 deletions(-) diff --git a/twoliter/src/project.rs b/twoliter/src/project.rs index eb00168d9..a4b932a4d 100644 --- a/twoliter/src/project.rs +++ b/twoliter/src/project.rs @@ -2,12 +2,13 @@ use crate::docker::ImageArchUri; use crate::schema_version::SchemaVersion; use anyhow::{ensure, Context, Result}; use async_recursion::async_recursion; -use log::{debug, trace}; +use log::{debug, info, trace, warn}; use non_empty_string::NonEmptyString; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha512}; use std::path::{Path, PathBuf}; use tokio::fs; +use toml::Table; /// Common functionality in commands, if the user gave a path to the `Twoliter.toml` file, /// we use it, otherwise we search for the file. Returns the `Project` and the path at which it was @@ -25,7 +26,7 @@ pub(crate) async fn load_or_find_project(user_path: Option) -> Result

, + release_version: String, + sdk: Option, + toolchain: Option, +} + +impl UnvalidatedProject { + /// Constructs a [`Project`] from an [`UnvalidatedProject`] after validating fields. + async fn validate(self, path: impl AsRef) -> Result { + let filepath: PathBuf = path.as_ref().into(); + let project_dir = filepath + .parent() + .context(format!( + "Unable to find the parent directory of '{}'", + filepath.display(), + ))? + .to_path_buf(); + + self.check_release_toml(&project_dir).await?; + + Ok(Project { + filepath, + project_dir, + schema_version: self.schema_version, + release_version: self.release_version, + sdk: self.sdk, + toolchain: self.toolchain, + }) + } + + /// Issues a warning if `Release.toml` is found and, if so, ensures that it contains the same + /// version (i.e. `release-version`) as the `Twoliter.toml` project file. + async fn check_release_toml(&self, project_dir: &Path) -> Result<()> { + let path = project_dir.join("Release.toml"); + if !path.exists() || !path.is_file() { + // There is no Release.toml file. This is a good thing! + trace!("This project does not have a Release.toml file (this is not a problem)"); + return Ok(()); + } + warn!( + "A Release.toml file was found. Release.toml is deprecated. Please remove it from \ + your project." + ); + let content = fs::read_to_string(&path).await.context(format!( + "Error while checking Release.toml file at '{}'", + path.display() + ))?; + let toml: Table = match toml::from_str(&content) { + Ok(toml) => toml, + Err(e) => { + warn!( + "Unable to parse Release.toml to ensure that its version matches the \ + release-version in Twoliter.toml: {e}", + ); + return Ok(()); + } + }; + let version = match toml.get("version") { + Some(version) => version, + None => { + info!("Release.toml does not contain a version key. Ignoring it."); + return Ok(()); + } + } + .to_string(); + ensure!( + version == self.release_version, + "The version found in Release.toml, '{version}', does not match the release-version \ + found in Twoliter.toml '{}'", + self.release_version + ); + Ok(()) + } +} + #[cfg(test)] mod test { use super::*;