mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 11:43:28 +03:00
Complete command
This commit is contained in:
parent
93b47602dd
commit
83065845df
@ -1,4 +1,4 @@
|
||||
use crate::commands::cli_types::*;
|
||||
use crate::cli_types::*;
|
||||
use crate::errors::CLIError;
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
@ -64,5 +64,5 @@ pub trait CLI {
|
||||
fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError>;
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(&mut self, options: Self::Options) -> Result<(), CLIError>;
|
||||
fn output(options: Self::Options) -> Result<(), CLIError>;
|
||||
}
|
63
leo/commands/init.rs
Normal file
63
leo/commands/init.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::directories::SourceDirectory;
|
||||
use crate::errors::{CLIError, InitError};
|
||||
use crate::manifest::Manifest;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::env::current_dir;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InitCommand;
|
||||
|
||||
impl CLI for InitCommand {
|
||||
type Options = Option<String>;
|
||||
|
||||
const NAME: NameType = "init";
|
||||
const ABOUT: AboutType = "Creates a new Leo package (include -h for more options)";
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<(), CLIError> {
|
||||
let name = options;
|
||||
let path = current_dir()?;
|
||||
|
||||
// Derive the package name
|
||||
let package_name = match name {
|
||||
Some(name) => name,
|
||||
None => path
|
||||
.file_stem()
|
||||
.ok_or_else(|| InitError::ProjectNameInvalid(path.as_os_str().to_owned()))?
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
// Verify the directory exists
|
||||
if !path.exists() {
|
||||
return Err(InitError::DirectoryDoesNotExist(path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Verify a manifest file does not already exist
|
||||
if Manifest::exists_at(&path) {
|
||||
return Err(InitError::PackageAlreadyExists(path.as_os_str().to_owned()).into());
|
||||
}
|
||||
Manifest::new(&package_name).write_to(&path)?;
|
||||
|
||||
// Create the source directory
|
||||
SourceDirectory::create(&path)?;
|
||||
|
||||
// if !MainFile::exists_at(&path) {
|
||||
// MainFile::new(&package_name)
|
||||
// .write_to(&path)
|
||||
// .map_err(Error::MainFile)?;
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
use crate::commands::{cli::*, cli_types::*};
|
||||
use crate::errors::{CLIError, ManifestError, NewError};
|
||||
use crate::manifest::Manifest;
|
||||
|
||||
use clap::{ArgMatches, Values};
|
||||
use colored::*;
|
||||
use rand::{rngs::StdRng, Rng};
|
||||
use rand_core::SeedableRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::from_str;
|
||||
use std::{fmt, fmt::Display, fs, str::FromStr};
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub struct InitCommand {
|
||||
#[structopt(parse(from_os_str))]
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl CLI for InitCommand {
|
||||
type Options = ();
|
||||
|
||||
const NAME: NameType = "init";
|
||||
const ABOUT: AboutType = "Creates a new Leo package (include -h for more options)";
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
let mut options = ();
|
||||
// options.parse(arguments, &["count", "format", "json", "network"]);
|
||||
//
|
||||
// match arguments.subcommand() {
|
||||
// ("hd", Some(arguments)) => {
|
||||
// options.subcommand = Some("hd".into());
|
||||
// options.parse(arguments, &["count", "json", "network"]);
|
||||
// options.parse(arguments, &["derivation", "language", "password", "word count"]);
|
||||
// }
|
||||
// _ => {}
|
||||
// };
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(&mut self, options: Self::Options) -> Result<(), CLIError> {
|
||||
let package_name = self.path
|
||||
.file_stem()
|
||||
.ok_or_else(|| NewError::ProjectNameInvalid(self.path.as_os_str().to_owned()))?
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
if self.path.exists() {
|
||||
return Err(NewError::DirectoryAlreadyExists(self.path.as_os_str().to_owned()).into());
|
||||
}
|
||||
fs::create_dir_all(&self.path).map_err(|error| {
|
||||
NewError::CreatingRootDirectory(self.path.as_os_str().to_owned(), error)
|
||||
})?;
|
||||
|
||||
Manifest::new(&package_name).write_to(&self.path).map_err(NewError::ManifestError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
@ -1,6 +1,2 @@
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
pub mod cli;
|
||||
pub mod cli_types;
|
||||
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
2
leo/directories/mod.rs
Normal file
2
leo/directories/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
61
leo/directories/source.rs
Normal file
61
leo/directories/source.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::errors::SourceDirectoryError;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(self) static DIRECTORY_NAME_DEFAULT: &str = "src/";
|
||||
|
||||
static SOURCE_FILE_EXTENSION_DEFAULT: &str = "leo";
|
||||
|
||||
pub struct SourceDirectory;
|
||||
|
||||
impl SourceDirectory {
|
||||
/// Creates a directory at the provided path with the default directory name.
|
||||
pub fn create(path: &PathBuf) -> Result<(), SourceDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(DIRECTORY_NAME_DEFAULT) {
|
||||
path.push(PathBuf::from(DIRECTORY_NAME_DEFAULT));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).map_err(SourceDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Returns a list of files in the source directory.
|
||||
pub fn files(path: &PathBuf) -> Result<Vec<PathBuf>, SourceDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
path.push(PathBuf::from(DIRECTORY_NAME_DEFAULT));
|
||||
let directory = fs::read_dir(&path).map_err(SourceDirectoryError::Reading)?;
|
||||
|
||||
let mut file_paths = Vec::new();
|
||||
for file_entry in directory.into_iter() {
|
||||
let file_entry = file_entry.map_err(SourceDirectoryError::GettingFileEntry)?;
|
||||
let file_path = file_entry.path();
|
||||
|
||||
// Verify that the entry is structured as a valid file
|
||||
let file_type = file_entry
|
||||
.file_type()
|
||||
.map_err(|error| SourceDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?;
|
||||
if !file_type.is_file() {
|
||||
return Err(SourceDirectoryError::InvalidFileType(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_type,
|
||||
));
|
||||
}
|
||||
|
||||
// Verify that the file has the default file extension
|
||||
let file_extension = file_path
|
||||
.extension()
|
||||
.ok_or_else(|| SourceDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?;
|
||||
if file_extension != SOURCE_FILE_EXTENSION_DEFAULT {
|
||||
return Err(SourceDirectoryError::InvalidFileExtension(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_extension.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
file_paths.push(file_path);
|
||||
}
|
||||
|
||||
Ok(file_paths)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::errors::{ManifestError, NewError};
|
||||
use crate::errors::{ManifestError, InitError, SourceDirectoryError};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum CLIError {
|
||||
@ -9,7 +9,10 @@ pub enum CLIError {
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
NewError(NewError),
|
||||
InitError(InitError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
SourceDirectoryError(SourceDirectoryError),
|
||||
}
|
||||
|
||||
impl From<ManifestError> for CLIError {
|
||||
@ -18,14 +21,26 @@ impl From<ManifestError> for CLIError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NewError> for CLIError {
|
||||
fn from(error: NewError) -> Self {
|
||||
CLIError::NewError(error)
|
||||
impl From<InitError> for CLIError {
|
||||
fn from(error: InitError) -> Self {
|
||||
CLIError::InitError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SourceDirectoryError> for CLIError {
|
||||
fn from(error: SourceDirectoryError) -> Self {
|
||||
CLIError::SourceDirectoryError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::error::Error> for CLIError {
|
||||
fn from(error: serde_json::error::Error) -> Self {
|
||||
CLIError::Crate("serde_json", format!("{:?}", error))
|
||||
CLIError::Crate("serde_json", format!("{}", error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for CLIError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
CLIError::Crate("std::io", format!("{}", error))
|
||||
}
|
||||
}
|
||||
|
@ -4,24 +4,27 @@ use std::ffi::OsString;
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum NewError {
|
||||
pub enum InitError {
|
||||
|
||||
#[fail(display = "root directory {:?} creating: {}", _0, _1)]
|
||||
CreatingRootDirectory(OsString, io::Error),
|
||||
|
||||
#[fail(display = "directory {:?} already exists", _0)]
|
||||
DirectoryAlreadyExists(OsString),
|
||||
#[fail(display = "directory {:?} does not exist", _0)]
|
||||
DirectoryDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "package at path {:?} already exists", _0)]
|
||||
PackageAlreadyExists(OsString),
|
||||
|
||||
#[fail(display = "package name is missing - {:?}", _0)]
|
||||
ProjectNameInvalid(OsString),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for NewError {
|
||||
impl From<ManifestError> for InitError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
NewError::ManifestError(error)
|
||||
InitError::ManifestError(error)
|
||||
}
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
pub mod new;
|
||||
pub use self::new::*;
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
2
leo/errors/directory/mod.rs
Normal file
2
leo/errors/directory/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
27
leo/errors/directory/source.rs
Normal file
27
leo/errors/directory/source.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum SourceDirectoryError {
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "file entry getting: {}", _0)]
|
||||
GettingFileEntry(io::Error),
|
||||
|
||||
#[fail(display = "file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[fail(display = "file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[fail(display = "invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
|
||||
#[fail(display = "invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[fail(display = "reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
}
|
@ -4,5 +4,8 @@ pub use self::cli::*;
|
||||
pub mod commands;
|
||||
pub use self::commands::*;
|
||||
|
||||
pub mod directory;
|
||||
pub use self::directory::*;
|
||||
|
||||
pub mod manifest;
|
||||
pub use self::manifest::*;
|
||||
|
@ -1,6 +1,10 @@
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
pub mod cli;
|
||||
pub mod cli_types;
|
||||
pub mod commands;
|
||||
pub mod directories;
|
||||
pub mod errors;
|
||||
pub mod manifest;
|
||||
|
@ -110,7 +110,7 @@
|
||||
// //
|
||||
// }
|
||||
|
||||
use leo::commands::{cli::*, InitCommand};
|
||||
use leo::{cli::*, commands::*};
|
||||
use leo::errors::CLIError;
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
@ -135,9 +135,9 @@ fn main() -> Result<(), CLIError> {
|
||||
|
||||
|
||||
match arguments.subcommand() {
|
||||
// ("init", Some(arguments)) => {
|
||||
// NewCommand::().output(NewCommand::parse(arguments)?)
|
||||
// },
|
||||
("init", Some(arguments)) => {
|
||||
InitCommand::output(InitCommand::parse(arguments)?)
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use failure::Fail;
|
||||
use serde::Deserialize;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
|
Loading…
Reference in New Issue
Block a user