diff --git a/leo/commands/init.rs b/leo/commands/init.rs index edd5081119..a4970ee5a5 100644 --- a/leo/commands/init.rs +++ b/leo/commands/init.rs @@ -5,7 +5,7 @@ use crate::{ }; use leo_package::{ inputs::*, - root::{Gitignore, Manifest}, + root::{Gitignore, Manifest, README}, source::{LibFile, MainFile, SourceDirectory}, }; @@ -58,6 +58,9 @@ impl CLI for InitCommand { // Create the .gitignore file Gitignore::new().write_to(&path)?; + // Create the README.md file + README::new(&package_name).write_to(&path)?; + // Create the source directory SourceDirectory::create(&path)?; diff --git a/leo/commands/publish.rs b/leo/commands/publish.rs index bc35c772cf..56a313d3b2 100644 --- a/leo/commands/publish.rs +++ b/leo/commands/publish.rs @@ -1,12 +1,13 @@ use crate::{ cli::*, cli_types::*, - commands::LoginCommand, + commands::{BuildCommand, LoginCommand}, credentials::{read_token, PACKAGE_MANAGER_URL}, errors::{ commands::PublishError::{ConnectionUnavalaible, PackageNotPublished}, CLIError, CLIError::PublishError, + PublishError::{MissingPackageDescription, MissingPackageLicense, MissingPackageRemote}, }, }; use leo_package::{ @@ -27,7 +28,6 @@ const PUBLISH_URL: &str = "api/package/publish"; #[derive(Deserialize)] struct ResponseJson { package_id: String, - _success: bool, } #[derive(Debug)] @@ -52,12 +52,27 @@ impl CLI for PublishCommand { #[cfg_attr(tarpaulin, skip)] fn output(_options: Self::Options) -> Result { // Build all program files. - // let _output = BuildCommand::output(options)?; + let _output = BuildCommand::output(())?; - // Get the package name + // Get the package manifest let path = current_dir()?; - let package_name = Manifest::try_from(&path)?.get_package_name(); - let package_version = Manifest::try_from(&path)?.get_package_version(); + let package_manifest = Manifest::try_from(&path)?; + + let package_name = package_manifest.get_package_name(); + let package_version = package_manifest.get_package_version(); + + if package_manifest.get_package_description().is_none() { + return Err(PublishError(MissingPackageDescription)); + } + + if package_manifest.get_package_license().is_none() { + return Err(PublishError(MissingPackageLicense)); + } + + let package_remote = match package_manifest.get_package_remote() { + Some(remote) => remote, + None => return Err(PublishError(MissingPackageRemote)), + }; // Create the output directory OutputsDirectory::create(&path)?; @@ -68,12 +83,13 @@ impl CLI for PublishCommand { log::debug!("Existing package zip file found. Clearing it to regenerate."); // Remove the existing package zip file ZipFile::new(&package_name).remove(&path)?; - } else { - zip_file.write(&path)?; } + zip_file.write(&path)?; + let form_data = Form::new() .text("name", package_name) + .text("remote", package_remote) .text("version", package_version) .file("file", zip_file.get_file_path(&path))?; @@ -123,7 +139,7 @@ impl CLI for PublishCommand { } }; - log::info!("Package published successfully"); + log::info!("Package published successfully with id: {}", result.package_id); Ok(Some(result.package_id)) } } diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index 1f3a1bb08e..99256fa69a 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -63,6 +63,9 @@ pub enum CLIError { #[error("{}", _0)] PublishError(PublishError), + #[error("{}", _0)] + READMEError(READMEError), + #[error("{}", _0)] RunError(RunError), @@ -215,6 +218,13 @@ impl From for CLIError { } } +impl From for CLIError { + fn from(error: READMEError) -> Self { + log::error!("{}\n", error); + CLIError::READMEError(error) + } +} + impl From for CLIError { fn from(error: RunError) -> Self { log::error!("{}\n", error); diff --git a/leo/errors/commands/publish.rs b/leo/errors/commands/publish.rs index ed98ba2d98..6ac376ce40 100644 --- a/leo/errors/commands/publish.rs +++ b/leo/errors/commands/publish.rs @@ -5,6 +5,15 @@ pub enum PublishError { #[error("connection unavailable {:?}", _0)] ConnectionUnavalaible(OsString), + #[error("package toml file is missing a description")] + MissingPackageDescription, + + #[error("package toml file is missing a license")] + MissingPackageLicense, + + #[error("package toml file is missing a remote")] + MissingPackageRemote, + #[error("package not published {:?}", _0)] PackageNotPublished(OsString), } diff --git a/package/src/errors/root/mod.rs b/package/src/errors/root/mod.rs index 8769ea2e5c..dfe9123776 100644 --- a/package/src/errors/root/mod.rs +++ b/package/src/errors/root/mod.rs @@ -4,5 +4,8 @@ pub use self::gitignore::*; pub mod manifest; pub use self::manifest::*; +pub mod readme; +pub use self::readme::*; + pub mod zip; pub use self::zip::*; diff --git a/package/src/errors/root/readme.rs b/package/src/errors/root/readme.rs new file mode 100644 index 0000000000..70d133638f --- /dev/null +++ b/package/src/errors/root/readme.rs @@ -0,0 +1,19 @@ +use std::io; + +#[derive(Debug, Error)] +pub enum READMEError { + #[error("{}: {}", _0, _1)] + Crate(&'static str, String), + + #[error("creating: {}", _0)] + Creating(io::Error), + + #[error("writing: {}", _0)] + Writing(io::Error), +} + +impl From for READMEError { + fn from(error: std::io::Error) -> Self { + READMEError::Crate("std::io", format!("{}", error)) + } +} diff --git a/package/src/root/manifest.rs b/package/src/root/manifest.rs index a439e1d31c..c4caf4e171 100644 --- a/package/src/root/manifest.rs +++ b/package/src/root/manifest.rs @@ -14,6 +14,9 @@ pub const MANIFEST_FILE_NAME: &str = "Leo.toml"; pub struct Package { pub name: String, pub version: String, + pub description: Option, + pub license: Option, + pub remote: Option, } #[derive(Deserialize)] @@ -27,6 +30,9 @@ impl Manifest { package: Package { name: package_name.to_owned(), version: "0.1.0".to_owned(), + description: None, + license: None, + remote: None, }, } } @@ -47,6 +53,18 @@ impl Manifest { self.package.version.clone() } + pub fn get_package_description(&self) -> Option { + self.package.description.clone() + } + + pub fn get_package_license(&self) -> Option { + self.package.license.clone() + } + + pub fn get_package_remote(&self) -> Option { + self.package.remote.clone() + } + pub fn write_to(self, path: &PathBuf) -> Result<(), ManifestError> { let mut path = path.to_owned(); if path.is_dir() { diff --git a/package/src/root/mod.rs b/package/src/root/mod.rs index 8769ea2e5c..dfe9123776 100644 --- a/package/src/root/mod.rs +++ b/package/src/root/mod.rs @@ -4,5 +4,8 @@ pub use self::gitignore::*; pub mod manifest; pub use self::manifest::*; +pub mod readme; +pub use self::readme::*; + pub mod zip; pub use self::zip::*; diff --git a/package/src/root/readme.rs b/package/src/root/readme.rs new file mode 100644 index 0000000000..aea6ec8917 --- /dev/null +++ b/package/src/root/readme.rs @@ -0,0 +1,47 @@ +//! The `README.md` file. + +use crate::errors::READMEError; + +use serde::Deserialize; +use std::{fs::File, io::Write, path::PathBuf}; + +pub static README_FILE_NAME: &str = "README.md"; + +#[derive(Deserialize)] +pub struct README { + pub package_name: String, +} + +impl README { + pub fn new(package_name: &str) -> Self { + Self { + package_name: package_name.to_string(), + } + } + + pub fn package_name(&self) -> String { + self.package_name.clone() + } + + pub fn exists_at(path: &PathBuf) -> bool { + let mut path = path.to_owned(); + if path.is_dir() { + path.push(PathBuf::from(README_FILE_NAME)); + } + path.exists() + } + + pub fn write_to(self, path: &PathBuf) -> Result<(), READMEError> { + let mut path = path.to_owned(); + if path.is_dir() { + path.push(PathBuf::from(README_FILE_NAME)); + } + + let mut file = File::create(&path)?; + Ok(file.write_all(self.template().as_bytes())?) + } + + fn template(&self) -> String { + format!("# {}\n", self.package_name) + } +}