mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
update revs, improve error handling, remove unused code
This commit is contained in:
parent
f4a32331b7
commit
dcd6501262
995
Cargo.lock
generated
995
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -52,12 +52,12 @@ version = "1.5.3"
|
||||
|
||||
[dependencies.aleo]
|
||||
git = "https://github.com/AleoHQ/aleo.git"
|
||||
rev = "03b12ff"
|
||||
rev = "a0895e0"
|
||||
|
||||
[dependencies.snarkvm]
|
||||
#path = "../snarkVM"
|
||||
git = "https://github.com/AleoHQ/snarkVM.git"
|
||||
rev = "18ee4e5"
|
||||
rev = "f25e0b2"
|
||||
features = ["circuit", "console"]
|
||||
|
||||
[dependencies.backtrace]
|
||||
|
@ -1,9 +0,0 @@
|
||||
[project]
|
||||
name = "hello"
|
||||
version = "0.3.0"
|
||||
description = "A minimal token program in Leo."
|
||||
license = "LICENSE-MIT"
|
||||
|
||||
[remote]
|
||||
author = "aleo"
|
||||
|
@ -1 +0,0 @@
|
||||
# hello-world
|
@ -1,3 +0,0 @@
|
||||
[main]
|
||||
r0: field = 1field;
|
||||
r1: field = 1field;
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"program": "hello.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"license": "MIT"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a + b;
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
build/
|
||||
outputs/
|
||||
/.leo
|
||||
build/
|
6
examples/helloworld/README.md
Normal file
6
examples/helloworld/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# helloworld.aleo
|
||||
## Build Guide
|
||||
To compile this Aleo program, run:
|
||||
```bash
|
||||
aleo build
|
||||
```
|
4
examples/helloworld/inputs/helloworld.in
Normal file
4
examples/helloworld/inputs/helloworld.in
Normal file
@ -0,0 +1,4 @@
|
||||
// The program input for helloworld/src/main.leo
|
||||
[main]
|
||||
a: u32 = 1u32;
|
||||
b: u32 = 2u32;
|
@ -1,4 +1,4 @@
|
||||
program hello.aleo;
|
||||
program helloworld.aleo;
|
||||
|
||||
function main:
|
||||
input r0 as u32.private;
|
10
examples/helloworld/program.json
Normal file
10
examples/helloworld/program.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"program": "helloworld.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"development": {
|
||||
"private_key": "APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx",
|
||||
"address": "aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
5
examples/helloworld/src/main.leo
Normal file
5
examples/helloworld/src/main.leo
Normal file
@ -0,0 +1,5 @@
|
||||
// The 'helloworld' main function.
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
let c: u32 = a + b;
|
||||
return c;
|
||||
}
|
2
examples/token/.gitignore
vendored
2
examples/token/.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
outputs/
|
||||
/.leo
|
||||
build/
|
||||
|
@ -1,8 +0,0 @@
|
||||
[project]
|
||||
name = "token"
|
||||
version = "0.3.0"
|
||||
description = "A simple token"
|
||||
license = "LICENSE-MIT"
|
||||
|
||||
[remote]
|
||||
author = "aleo"
|
6
examples/token/README.md
Normal file
6
examples/token/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# token.aleo
|
||||
## Build Guide
|
||||
To compile this Aleo program, run:
|
||||
```bash
|
||||
aleo build
|
||||
```
|
@ -1,3 +1,4 @@
|
||||
// The program input for token/src/main.leo
|
||||
[main]
|
||||
|
||||
[registers]
|
||||
a: u32 = 1u32;
|
||||
b: u32 = 2u32;
|
||||
|
10
examples/token/program.json
Normal file
10
examples/token/program.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"program": "token.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"development": {
|
||||
"private_key": "APrivateKey1zkpBqRv2cwkSiR4hQ3Tb4AZFD3XzdwPqV9QsEykTKBV1YKT",
|
||||
"address": "aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
@ -20,14 +20,14 @@ use leo_compiler::{Ast, Compiler, InputAst, OutputOptions};
|
||||
use leo_errors::{CliError, Result};
|
||||
use leo_package::{
|
||||
inputs::InputFile,
|
||||
// inputs::*,
|
||||
// outputs::CircuitFile
|
||||
outputs::{ChecksumFile, OutputsDirectory, MAIN_ALEO_FILE_NAME, OUTPUTS_DIRECTORY_NAME},
|
||||
outputs::{ChecksumFile, OutputsDirectory, OUTPUTS_DIRECTORY_NAME},
|
||||
source::{MainFile, MAIN_FILENAME, SOURCE_DIRECTORY_NAME},
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
use aleo::commands::Build as AleoBuild;
|
||||
|
||||
use clap::StructOpt;
|
||||
use std::str::FromStr;
|
||||
use tracing::span::Span;
|
||||
|
||||
/// Compiler Options wrapper for Build command. Also used by other commands which
|
||||
@ -86,15 +86,11 @@ impl Command for Build {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Get the package path.
|
||||
let path = context.dir()?;
|
||||
let manifest = context.manifest().map_err(|_| CliError::manifest_file_not_found())?;
|
||||
let package_name = manifest.program_id().name().to_string();
|
||||
// let imports_map = manifest.get_imports_map().unwrap_or_default();
|
||||
//
|
||||
// // Error out if there are dependencies but no lock file found.
|
||||
// if !imports_map.is_empty() && !context.lock_file_exists()? {
|
||||
// return Err(CliError::dependencies_are_not_installed().into());
|
||||
// }
|
||||
|
||||
// Get the package name.
|
||||
let package_name = context.program_name()?;
|
||||
|
||||
// Sanitize the package path to the root directory.
|
||||
let mut package_path = path.clone();
|
||||
@ -113,9 +109,6 @@ impl Command for Build {
|
||||
return Err(CliError::package_main_file_not_found().into());
|
||||
}
|
||||
|
||||
// Create the output directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
// Construct the path to the main file in the source directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(SOURCE_DIRECTORY_NAME);
|
||||
@ -124,33 +117,12 @@ impl Command for Build {
|
||||
// Load the input file at `package_name.in`
|
||||
let input_path = InputFile::new(&package_name).setup_file_path(&path);
|
||||
|
||||
// Load the state file at `package_name.in`
|
||||
// let (state_string, state_path) = StateFile::new(&package_name).read_from(&path)?;
|
||||
// Create the outputs directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
// Log compilation of files to console
|
||||
tracing::info!("Compiling main program... ({:?})", main_file_path);
|
||||
|
||||
// let imports_map = if context.lock_file_exists()? {
|
||||
// context.lock_file()?.to_import_map()
|
||||
// } else {
|
||||
// Default::default()
|
||||
// };
|
||||
|
||||
// Load the program at `main_file_path`
|
||||
// let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_input(
|
||||
// package_name.clone(),
|
||||
// main_file_path,
|
||||
// output_directory,
|
||||
// &input_string,
|
||||
// &input_path,
|
||||
// &state_string,
|
||||
// &state_path,
|
||||
// thread_leaked_context(),
|
||||
// Some(self.compiler_options.clone().into()),
|
||||
// imports_map,
|
||||
// Some(self.compiler_options.into()),
|
||||
// )?;
|
||||
|
||||
// Initialize error handler
|
||||
let handler = leo_errors::emitter::Handler::default();
|
||||
|
||||
@ -170,35 +142,24 @@ impl Command for Build {
|
||||
|
||||
// Compile the program.
|
||||
{
|
||||
let program_id_string = format!("{}.aleo", package_name); // todo: read this from a config file.
|
||||
// Compile the Leo program into Aleo instructions.
|
||||
let (_, instructions) = program.compile_and_generate_instructions()?;
|
||||
|
||||
// Parse the generated instructions into an Aleo file.
|
||||
let file =
|
||||
AleoFile::<Testnet3>::from_str(&instructions).expect("Failed to parse generated Aleo instructions.");
|
||||
// Parse the generated Aleo instructions into an Aleo file.
|
||||
let file = AleoFile::<Network>::from_str(&instructions).map_err(CliError::failed_to_load_instructions)?;
|
||||
|
||||
// Create the path to the Aleo file.
|
||||
let mut aleo_file_path = package_path.clone();
|
||||
aleo_file_path.push(AleoFile::<Network>::main_file_name());
|
||||
|
||||
// Write the Aleo file to `main.aleo`.
|
||||
let mut aleo_file_path = package_path.clone();
|
||||
aleo_file_path.push(MAIN_ALEO_FILE_NAME);
|
||||
file.write_to(&aleo_file_path)
|
||||
.map_err(|err| CliError::failed_to_write_to_aleo_file(aleo_file_path.display(), err))?;
|
||||
|
||||
file.write_to(&aleo_file_path).expect("Failed to write the aleo file.");
|
||||
|
||||
// Initialize the program id.
|
||||
let program_id =
|
||||
ProgramID::<Testnet3>::from_str(&program_id_string).expect("Failed to parse program id from string.");
|
||||
|
||||
// Create the program.json file to the output directory.
|
||||
let _manifest_file = if Manifest::<Testnet3>::exists_at(&package_path) {
|
||||
Manifest::<Testnet3>::open(&package_path).expect("Failed to open manifest file.")
|
||||
} else {
|
||||
Manifest::<Testnet3>::create(&package_path, &program_id).expect("Failed to create manifest file.")
|
||||
};
|
||||
|
||||
// Call the `build` command from the Aleo SDK.
|
||||
// todo error: thread 'main' panicked at 'Failed to call `aleo build` command from the Aleo SDK: Development private key not found.', leo/commands/build.rs:203:37
|
||||
// let build = aleo::commands::Build;
|
||||
// let res = build.parse().expect("Failed to call `aleo build` command from the Aleo SDK");
|
||||
// tracing::info!("Result: {}", res);
|
||||
// Call the `aleo build` command from the Aleo SDK.
|
||||
let res = AleoBuild.parse().map_err(CliError::failed_to_call_aleo_build)?;
|
||||
// Log the result of the build
|
||||
tracing::info!("Result: {}", res);
|
||||
}
|
||||
|
||||
// If a checksum file exists, check if it differs from the new checksum
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{commands::Command, context::Context};
|
||||
use leo_errors::Result;
|
||||
use leo_package::outputs::ChecksumFile;
|
||||
// use leo_package::outputs::ChecksumFile;
|
||||
|
||||
use clap::StructOpt;
|
||||
use tracing::span::Span;
|
||||
@ -37,14 +37,14 @@ impl Command for Clean {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
let path = context.dir()?;
|
||||
let package_name = context.manifest()?.program_id().name().to_string();
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// let path = context.dir()?;
|
||||
// let package_name = context.manifest()?.program_id().name().to_string();
|
||||
|
||||
// Removes the aleo file from the output directory.
|
||||
|
||||
// Remove the checksum from the output directory
|
||||
ChecksumFile::new(&package_name).remove(&path)?;
|
||||
// ChecksumFile::new(&package_name).remove(&path)?;
|
||||
|
||||
// // Remove the serialized circuit from the output directory
|
||||
// CircuitFile::new(&package_name).remove(&path)?;
|
||||
|
@ -21,26 +21,25 @@ pub use build::Build;
|
||||
pub mod clean;
|
||||
pub use clean::Clean;
|
||||
|
||||
pub mod new;
|
||||
pub use new::New;
|
||||
|
||||
pub mod run;
|
||||
pub use run::Run;
|
||||
|
||||
// pub mod init;
|
||||
// pub use init::Init;
|
||||
|
||||
// pub mod new;
|
||||
// pub use new::New;
|
||||
|
||||
use crate::context::*;
|
||||
use leo_errors::Result;
|
||||
|
||||
use snarkvm::{
|
||||
console::{network::Testnet3, program::ProgramID},
|
||||
file::{AleoFile, Manifest},
|
||||
};
|
||||
use snarkvm::file::AleoFile;
|
||||
|
||||
use std::time::Instant;
|
||||
use tracing::span::Span;
|
||||
|
||||
pub(crate) type Network = snarkvm::prelude::Testnet3;
|
||||
|
||||
/// Base trait for the Leo CLI, see methods and their documentation for details.
|
||||
pub trait Command {
|
||||
/// If the current command requires running another command beforehand
|
||||
|
@ -14,17 +14,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{commands::Command, config::*, context::Context};
|
||||
use leo_errors::{CliError, Result};
|
||||
use leo_package::LeoPackage;
|
||||
use crate::{commands::Command, context::Context};
|
||||
use leo_errors::{PackageError, Result};
|
||||
use leo_package::package::Package;
|
||||
|
||||
use std::fs;
|
||||
use structopt::StructOpt;
|
||||
use aleo::commands::New as AleoNew;
|
||||
|
||||
use clap::StructOpt;
|
||||
use tracing::span::Span;
|
||||
|
||||
/// Create new Leo project
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||
pub struct New {
|
||||
#[structopt(name = "NAME", help = "Set package name")]
|
||||
name: String,
|
||||
@ -42,28 +42,22 @@ impl Command for New {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Check that the given package name is valid.
|
||||
let package_name = self.name;
|
||||
if !LeoPackage::is_package_name_valid(&package_name) {
|
||||
return Err(CliError::invalid_project_name().into());
|
||||
}
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Call the `aleo new` command from the Aleo SDK.
|
||||
let command = AleoNew::try_parse_from(&["aleo", &self.name]).expect("Failed to parse `aleo new` command");
|
||||
let result = command.parse().expect("Failed to create a new Aleo project");
|
||||
|
||||
let username = read_username().ok();
|
||||
// Derive the program directory path.
|
||||
let mut path = std::env::current_dir().map_err(|e| PackageError::io_error("current directory", e))?;
|
||||
path.push(&self.name);
|
||||
|
||||
// Derive the package directory path.
|
||||
let mut path = context.dir()?;
|
||||
path.push(&package_name);
|
||||
// Initialize the Leo package in the directory created by `aleo new`.
|
||||
Package::initialize(&self.name, &path)?;
|
||||
|
||||
// Verify the package directory path does not exist yet.
|
||||
if path.exists() {
|
||||
return Err(CliError::package_directory_already_exists(&path).into());
|
||||
}
|
||||
// todo: modify the readme file to build with `leo build`.
|
||||
|
||||
// Create the package directory
|
||||
fs::create_dir_all(&path).map_err(CliError::package_could_not_create_directory)?;
|
||||
|
||||
LeoPackage::initialize(&package_name, &path, username)?;
|
||||
// Log success.
|
||||
tracing::info!("{}", result);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -14,28 +14,26 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{api::Api, config};
|
||||
use crate::commands::Network;
|
||||
use leo_errors::{CliError, Result};
|
||||
|
||||
use snarkvm::file::Manifest;
|
||||
use snarkvm::prelude::Testnet3;
|
||||
|
||||
use std::{env::current_dir, path::PathBuf};
|
||||
|
||||
pub const PACKAGE_MANAGER_URL: &str = "https://api.aleo.pm/";
|
||||
|
||||
/// Project context, manifest, current directory etc
|
||||
/// All the info that is relevant in most of the commands
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
/// Api client for Aleo PM
|
||||
pub api: Api,
|
||||
|
||||
/// Path at which the command is called, None when default
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(path: Option<PathBuf>) -> Result<Context> {
|
||||
Ok(Context { path })
|
||||
}
|
||||
|
||||
/// Returns the path to the Leo package.
|
||||
pub fn dir(&self) -> Result<PathBuf> {
|
||||
match &self.path {
|
||||
Some(path) => Ok(path.clone()),
|
||||
@ -43,26 +41,16 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get package manifest for current context.
|
||||
pub fn manifest(&self) -> Result<Manifest<Testnet3>> {
|
||||
Ok(Manifest::<Testnet3>::open(self.dir()?.as_path())?)
|
||||
/// Returns the program name as a String.
|
||||
pub fn program_name(&self) -> Result<String> {
|
||||
// Open the manifest file.
|
||||
let path = self.dir()?;
|
||||
let manifest = Manifest::<Network>::open(&path).map_err(CliError::failed_to_open_manifest)?;
|
||||
|
||||
// Lookup the program id.
|
||||
let program_id = manifest.program_id();
|
||||
|
||||
// Get package name from program id.
|
||||
Ok(program_id.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new context for the current directory.
|
||||
pub fn create_context(path: PathBuf, api_url: Option<String>) -> Result<Context> {
|
||||
let token = config::read_token().ok();
|
||||
|
||||
let api = Api::new(api_url.unwrap_or_else(|| PACKAGE_MANAGER_URL.to_string()), token);
|
||||
|
||||
Ok(Context { api, path: Some(path) })
|
||||
}
|
||||
|
||||
/// Returns project context.
|
||||
pub fn get_context(api_url: Option<String>) -> Result<Context> {
|
||||
let token = config::read_token().ok();
|
||||
|
||||
let api = Api::new(api_url.unwrap_or_else(|| PACKAGE_MANAGER_URL.to_string()), token);
|
||||
|
||||
Ok(Context { api, path: None })
|
||||
}
|
||||
|
@ -400,6 +400,34 @@ create_messages!(
|
||||
msg: "unable to parse imported dependency's manifest",
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_open_manifest {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to open manifest file: {}", error),
|
||||
help: Some("Create a package by running `leo new`.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_load_instructions {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to load compiled Aleo instructions into an Aleo file: {}", error),
|
||||
help: Some("This is a Leo code generation bug. Please report it to https://github.com/AleoHQ/leo/issues/new/choose".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_write_to_aleo_file {
|
||||
args: (path: impl Display, error: impl Display),
|
||||
msg: format!("Failed to write to the Aleo file at `{}`. Error: {}", path, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_call_aleo_build {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to call the `aleo build` command. Error: {}", error),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
||||
impl CliError {
|
||||
|
@ -172,61 +172,61 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when creating the manifest file failed.
|
||||
@backtraced
|
||||
failed_to_create_manifest_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed creating manifest file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when parsing the manifest file failed.
|
||||
@backtraced
|
||||
failed_to_parse_manifest_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed parsing manifest file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when opening the manifest file failed.
|
||||
@backtraced
|
||||
failed_to_open_manifest_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed openining manifest file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when reading the manifest file failed.
|
||||
@backtraced
|
||||
failed_to_read_manifest_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed reading manifest file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when writing the manifest file failed.
|
||||
@backtraced
|
||||
failed_to_write_manifest_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed writing manifest file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when the manifest file has an IO error.
|
||||
@backtraced
|
||||
io_error_manifest_file {
|
||||
args: (error: impl ErrorArg),
|
||||
msg: format!("IO error manifest file from the provided file path - {}", error),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when getting the manifest metadata file failed.
|
||||
@backtraced
|
||||
failed_to_get_manifest_metadata_file {
|
||||
args: (filename: impl Display, error: impl ErrorArg),
|
||||
msg: format!("failed getting manifest metadata file `{}` {}", filename, error),
|
||||
help: None,
|
||||
}
|
||||
// /// For when creating the manifest file failed.
|
||||
// @backtraced
|
||||
// failed_to_create_manifest_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed creating manifest file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when parsing the manifest file failed.
|
||||
// @backtraced
|
||||
// failed_to_parse_manifest_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed parsing manifest file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when opening the manifest file failed.
|
||||
// @backtraced
|
||||
// failed_to_open_manifest_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed openining manifest file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when reading the manifest file failed.
|
||||
// @backtraced
|
||||
// failed_to_read_manifest_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed reading manifest file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when writing the manifest file failed.
|
||||
// @backtraced
|
||||
// failed_to_write_manifest_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed writing manifest file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when the manifest file has an IO error.
|
||||
// @backtraced
|
||||
// io_error_manifest_file {
|
||||
// args: (error: impl ErrorArg),
|
||||
// msg: format!("IO error manifest file from the provided file path - {}", error),
|
||||
// help: None,
|
||||
// }
|
||||
//
|
||||
// /// For when getting the manifest metadata file failed.
|
||||
// @backtraced
|
||||
// failed_to_get_manifest_metadata_file {
|
||||
// args: (filename: impl Display, error: impl ErrorArg),
|
||||
// msg: format!("failed getting manifest metadata file `{}` {}", filename, error),
|
||||
// help: None,
|
||||
// }
|
||||
|
||||
|
||||
/// For when creating the zip file failed.
|
||||
|
@ -16,9 +16,7 @@
|
||||
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod api;
|
||||
pub mod commands;
|
||||
pub mod config;
|
||||
pub mod context;
|
||||
pub mod logger;
|
||||
pub mod updater;
|
||||
|
214
leo/main.rs
214
leo/main.rs
@ -14,9 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod api;
|
||||
pub mod commands;
|
||||
pub mod config;
|
||||
pub mod context;
|
||||
pub mod logger;
|
||||
pub mod updater;
|
||||
@ -64,11 +62,11 @@ enum Commands {
|
||||
// command: Init,
|
||||
// },
|
||||
//
|
||||
// #[structopt(about = "Create a new Leo package in a new directory")]
|
||||
// New {
|
||||
// #[structopt(flatten)]
|
||||
// command: New,
|
||||
// },
|
||||
#[structopt(about = "Create a new Leo package in a new directory")]
|
||||
New {
|
||||
#[structopt(flatten)]
|
||||
command: New,
|
||||
},
|
||||
#[structopt(about = "Compile the current package as a program")]
|
||||
Build {
|
||||
#[structopt(flatten)]
|
||||
@ -140,14 +138,11 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
|
||||
|
||||
// Get custom root folder and create context for it.
|
||||
// If not specified, default context will be created in cwd.
|
||||
let context = handle_error(match cli.path {
|
||||
Some(path) => create_context(path, cli.api),
|
||||
None => get_context(cli.api),
|
||||
});
|
||||
let context = handle_error(Context::new(cli.path));
|
||||
|
||||
match cli.command {
|
||||
// CommandOpts::Init { command } => command.try_execute(context),
|
||||
// CommandOpts::New { command } => command.try_execute(context),
|
||||
Commands::New { command } => command.try_execute(context),
|
||||
Commands::Build { command } => command.try_execute(context),
|
||||
Commands::Clean { command } => command.try_execute(context),
|
||||
Commands::Run { command } => command.try_execute(context),
|
||||
@ -158,198 +153,3 @@ fn main() {
|
||||
set_panic_hook();
|
||||
create_session_if_not_set_then(|_| handle_error(run_with_args(CLI::parse())));
|
||||
}
|
||||
|
||||
// todo (collin): uncomment after refactor
|
||||
// #[cfg(test)]
|
||||
// mod cli_tests {
|
||||
// use crate::{run_with_args, Opt};
|
||||
// use leo_errors::{CliError, Result};
|
||||
//
|
||||
// use snarkvm_utilities::Write;
|
||||
// use std::path::PathBuf;
|
||||
// use structopt::StructOpt;
|
||||
// use test_dir::{DirBuilder, FileType, TestDir};
|
||||
//
|
||||
// // Runs Command from cmd-like argument "leo run --arg1 --arg2".
|
||||
// fn run_cmd(args: &str, path: &Option<PathBuf>) -> Result<()> {
|
||||
// let args = args.split(' ').collect::<Vec<&str>>();
|
||||
// let mut opts = Opt::from_iter_safe(args).map_err(CliError::opt_args_error)?;
|
||||
//
|
||||
// if path.is_some() {
|
||||
// opts.path = path.clone();
|
||||
// }
|
||||
//
|
||||
// if !opts.debug {
|
||||
// // turn off tracing for all tests
|
||||
// opts.quiet = true;
|
||||
// }
|
||||
//
|
||||
// run_with_args(opts)
|
||||
// }
|
||||
//
|
||||
// // Create a test directory with name.
|
||||
// fn testdir(name: &str) -> TestDir {
|
||||
// TestDir::temp().create(name, FileType::Dir)
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn global_options() {
|
||||
// let path = Some(PathBuf::from("examples/pedersen-hash"));
|
||||
//
|
||||
// assert!(run_cmd("leo build", &path).is_ok());
|
||||
// assert!(run_cmd("leo -q build", &path).is_ok());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn global_options_fail() {
|
||||
// assert!(run_cmd("leo --path ../../examples/no-directory-there build", &None).is_err());
|
||||
// assert!(run_cmd("leo -v build", &None).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn init() {
|
||||
// let dir = testdir("test");
|
||||
// let path = Some(dir.path("test"));
|
||||
//
|
||||
// assert!(run_cmd("leo init", &path).is_ok());
|
||||
// assert!(run_cmd("leo init", &path).is_err()); // 2nd time
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn init_fail() {
|
||||
// let dir = testdir("incorrect_name");
|
||||
// let path = Some(dir.path("incorrect_name"));
|
||||
// let fake = Some(PathBuf::from("no_such_directory"));
|
||||
//
|
||||
// assert!(run_cmd("leo init", &fake).is_err());
|
||||
// assert!(run_cmd("leo init", &path).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn new() {
|
||||
// let dir = testdir("new");
|
||||
// let path = Some(dir.path("new"));
|
||||
//
|
||||
// assert!(run_cmd("leo new test", &path).is_ok());
|
||||
// assert!(run_cmd("leo new test", &path).is_err()); // 2nd time
|
||||
// assert!(run_cmd("leo new wrong_name", &path).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[should_panic]
|
||||
// fn unimplemented() {
|
||||
// assert!(run_cmd("leo lint", &None).is_err());
|
||||
// assert!(run_cmd("leo deploy", &None).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn clean() {
|
||||
// let path = &Some(PathBuf::from("examples/pedersen-hash"));
|
||||
//
|
||||
// assert!(run_cmd("leo build", path).is_ok());
|
||||
// assert!(run_cmd("leo clean", path).is_ok());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn build_optimizations() {
|
||||
// let dir = testdir("build-test");
|
||||
// let path = dir.path("build-test");
|
||||
//
|
||||
// assert!(run_cmd("leo new setup-test", &Some(path.clone())).is_ok());
|
||||
//
|
||||
// let build_path = &Some(path.join("setup-test"));
|
||||
//
|
||||
// assert!(run_cmd("leo build --disable-all-optimizations", build_path).is_ok());
|
||||
// assert!(run_cmd("leo build --disable-code-elimination", build_path).is_ok());
|
||||
// assert!(run_cmd("leo build --disable-constant-folding", build_path).is_ok());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn setup_prove_run_clean() {
|
||||
// let dir = testdir("test");
|
||||
// let path = dir.path("test");
|
||||
//
|
||||
// assert!(run_cmd("leo new setup-test", &Some(path.clone())).is_ok());
|
||||
//
|
||||
// let setup_path = &Some(path.join("setup-test"));
|
||||
//
|
||||
// assert!(run_cmd("leo setup", setup_path).is_ok());
|
||||
// assert!(run_cmd("leo setup", setup_path).is_ok());
|
||||
// assert!(run_cmd("leo setup --skip-key-check", setup_path).is_ok());
|
||||
// assert!(run_cmd("leo prove --skip-key-check", setup_path).is_ok());
|
||||
// assert!(run_cmd("leo run --skip-key-check", setup_path).is_ok());
|
||||
// assert!(run_cmd("leo clean", setup_path).is_ok());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn test_import() {
|
||||
// let dir = testdir("test");
|
||||
// let path = dir.path("test");
|
||||
//
|
||||
// assert!(run_cmd("leo new import", &Some(path.clone())).is_ok());
|
||||
//
|
||||
// let import_path = &Some(path.join("import"));
|
||||
//
|
||||
// assert!(run_cmd("leo add no-package/definitely-no", import_path).is_err());
|
||||
// assert!(run_cmd("leo add justice-league/u8u32", import_path).is_ok());
|
||||
// assert!(run_cmd("leo remove u8u32", import_path).is_ok());
|
||||
// assert!(run_cmd("leo add --author justice-league --package u8u32", import_path).is_ok());
|
||||
// assert!(run_cmd("leo remove u8u32", import_path).is_ok());
|
||||
// assert!(run_cmd("leo remove u8u32", import_path).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_missing_file() {
|
||||
// let dir = testdir("test");
|
||||
// let path = dir.path("test");
|
||||
//
|
||||
// assert!(run_cmd("leo new test-file-missing", &Some(path.clone())).is_ok());
|
||||
//
|
||||
// let path = path.join("test-file-missing");
|
||||
// let file = path.join("src/main.leo");
|
||||
// let path = Some(path);
|
||||
//
|
||||
// assert!(run_cmd("leo test", &path).is_ok());
|
||||
// std::fs::remove_file(&file).unwrap();
|
||||
// assert!(run_cmd("leo test", &path).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_sudoku() {
|
||||
// let path = &Some(PathBuf::from("examples/silly-sudoku"));
|
||||
//
|
||||
// assert!(run_cmd("leo build", path).is_ok());
|
||||
// assert!(run_cmd("leo test", path).is_ok());
|
||||
// assert!(run_cmd("leo test -f examples/silly-sudoku/src/lib.leo", path).is_ok());
|
||||
// assert!(run_cmd("leo test -f examples/silly-sudoku/src/main.leo", path).is_ok());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_install() {
|
||||
// let dir = testdir("test");
|
||||
// let path = dir.path("test");
|
||||
//
|
||||
// assert!(run_cmd("leo new install", &Some(path.clone())).is_ok());
|
||||
//
|
||||
// let install_path = &Some(path.join("install"));
|
||||
//
|
||||
// let mut file = std::fs::OpenOptions::new()
|
||||
// .write(true)
|
||||
// .append(true)
|
||||
// .open(path.join("install/Leo.toml"))
|
||||
// .unwrap();
|
||||
//
|
||||
// assert!(run_cmd("leo fetch", install_path).is_ok());
|
||||
// assert!(file
|
||||
// .write_all(
|
||||
// br#"
|
||||
// sudoku = {author = "justice-league", package = "u8u32", version = "0.1.0"}
|
||||
// "#
|
||||
// )
|
||||
// .is_ok());
|
||||
//
|
||||
// assert!(run_cmd("leo fetch", install_path).is_ok());
|
||||
// assert!(run_cmd("leo build", install_path).is_ok());
|
||||
// }
|
||||
// }
|
||||
|
@ -76,11 +76,8 @@ impl InputFile {
|
||||
format!(
|
||||
r#"// The program input for {}/src/main.leo
|
||||
[main]
|
||||
a: u32 = 1;
|
||||
b: u32 = 2;
|
||||
|
||||
[registers]
|
||||
r0: u32 = 0;
|
||||
a: u32 = 1u32;
|
||||
b: u32 = 2u32;
|
||||
"#,
|
||||
self.package_name
|
||||
)
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
inputs::{InputFile, InputsDirectory},
|
||||
root::{Gitignore, README},
|
||||
root::Gitignore,
|
||||
source::{MainFile, SourceDirectory},
|
||||
};
|
||||
|
||||
@ -157,40 +157,25 @@ impl Package {
|
||||
true
|
||||
}
|
||||
|
||||
/// Creates a package at the given path
|
||||
pub fn initialize(package_name: &str, path: &Path, _author: Option<String>) -> Result<()> {
|
||||
// First, verify that this directory is not already initialized as a Leo package.
|
||||
{
|
||||
if !Self::can_initialize(package_name, path) {
|
||||
return Err(PackageError::failed_to_initialize_package(package_name, path.as_os_str()).into());
|
||||
}
|
||||
/// Creates a Leo package at the given path
|
||||
pub fn initialize(package_name: &str, path: &Path) -> Result<()> {
|
||||
// Verify that the .gitignore file does not exist.
|
||||
if !Gitignore::exists_at(path) {
|
||||
// Create the .gitignore file.
|
||||
Gitignore::new().write_to(path)?;
|
||||
}
|
||||
// Next, initialize this directory as a Leo package.
|
||||
{
|
||||
// Verify that the .gitignore file does not exist.
|
||||
if !Gitignore::exists_at(path) {
|
||||
// Create the .gitignore file.
|
||||
Gitignore::new().write_to(path)?;
|
||||
}
|
||||
|
||||
// Verify that the README.md file does not exist.
|
||||
if !README::exists_at(path) {
|
||||
// Create the README.md file.
|
||||
README::new(package_name).write_to(path)?;
|
||||
}
|
||||
// Create the source directory.
|
||||
SourceDirectory::create(path)?;
|
||||
|
||||
// Create the source directory.
|
||||
SourceDirectory::create(path)?;
|
||||
// Create the input directory.
|
||||
InputsDirectory::create(path)?;
|
||||
|
||||
// Create the input directory.
|
||||
InputsDirectory::create(path)?;
|
||||
// Create the input file in the inputs directory.
|
||||
InputFile::new(package_name).write_to(path)?;
|
||||
|
||||
// Create the input file in the inputs directory.
|
||||
InputFile::new(package_name).write_to(path)?;
|
||||
|
||||
// Create the main file in the source directory.
|
||||
MainFile::new(package_name).write_to(path)?;
|
||||
}
|
||||
// Create the main file in the source directory.
|
||||
MainFile::new(package_name).write_to(path)?;
|
||||
// Next, verify that a valid Leo package has been initialized in this directory
|
||||
{
|
||||
if !Self::is_initialized(package_name, path) {
|
||||
|
@ -52,6 +52,6 @@ impl Gitignore {
|
||||
}
|
||||
|
||||
fn template(&self) -> String {
|
||||
"outputs/\n".to_string()
|
||||
"outputs/\nbuild/\n".to_string()
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,3 @@
|
||||
|
||||
pub mod gitignore;
|
||||
pub use self::gitignore::*;
|
||||
|
||||
pub mod readme;
|
||||
pub use self::readme::*;
|
||||
|
@ -1,90 +0,0 @@
|
||||
// Copyright (C) 2019-2022 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
//! The `README.md` file.
|
||||
|
||||
use leo_errors::{PackageError, Result};
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::{borrow::Cow, fs::File, io::Write, path::Path};
|
||||
|
||||
pub static README_FILENAME: &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: &Path) -> bool {
|
||||
let mut path = Cow::from(path);
|
||||
if path.is_dir() {
|
||||
path.to_mut().push(README_FILENAME);
|
||||
}
|
||||
path.exists()
|
||||
}
|
||||
|
||||
pub fn write_to(self, path: &Path) -> Result<()> {
|
||||
let mut path = Cow::from(path);
|
||||
if path.is_dir() {
|
||||
path.to_mut().push(README_FILENAME);
|
||||
}
|
||||
|
||||
let mut file = File::create(&path).map_err(PackageError::io_error_readme_file)?;
|
||||
|
||||
file.write_all(self.template().as_bytes())
|
||||
.map_err(PackageError::io_error_readme_file)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn template(&self) -> String {
|
||||
format!(
|
||||
r"# {}
|
||||
|
||||
## Build Guide
|
||||
|
||||
To compile this Leo program, run:
|
||||
```bash
|
||||
leo build
|
||||
```
|
||||
|
||||
To test this Leo program, run:
|
||||
```bash
|
||||
leo test
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
To output the number of constraints, run:
|
||||
```bash
|
||||
leo build -d
|
||||
```
|
||||
",
|
||||
self.package_name
|
||||
)
|
||||
}
|
||||
}
|
@ -14,4 +14,4 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod initialize;
|
||||
// pub mod initialize;
|
||||
|
@ -16,59 +16,59 @@
|
||||
|
||||
#![allow(clippy::module_inception)]
|
||||
|
||||
pub mod initialize;
|
||||
pub mod manifest;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
env, fs,
|
||||
path::PathBuf,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
const PACKAGE_TEST_DIRECTORY: &str = "package-testing";
|
||||
|
||||
thread_local! {
|
||||
/// Establish a test id for each test.
|
||||
pub static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Create a testing directory for packages in `target/`
|
||||
pub static ref TEST_DIR: PathBuf = {
|
||||
let mut path = env::current_exe().unwrap();
|
||||
path.pop(); // Remove executable name
|
||||
path.pop(); // Remove 'debug'
|
||||
|
||||
// Attempt to point at the `target` directory
|
||||
if path.file_name().and_then(|s| s.to_str()) != Some("target") {
|
||||
path.pop();
|
||||
}
|
||||
|
||||
path.push(PACKAGE_TEST_DIRECTORY);
|
||||
fs::create_dir_all(&path).unwrap();
|
||||
|
||||
path
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a new directory for each test based on the ID of the test.
|
||||
pub(crate) fn test_dir() -> PathBuf {
|
||||
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
TEST_ID.with(|n| *n.borrow_mut() = Some(id));
|
||||
|
||||
let path: PathBuf = TEST_DIR.join(&format!("t{}", id));
|
||||
|
||||
if path.exists() {
|
||||
if let Err(e) = fs::remove_dir_all(&path) {
|
||||
panic!("failed to remove {:?}: {:?}", &path, e)
|
||||
}
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).unwrap();
|
||||
|
||||
path
|
||||
}
|
||||
// pub mod initialize;
|
||||
// pub mod manifest;
|
||||
//
|
||||
// use lazy_static::lazy_static;
|
||||
// use std::{
|
||||
// cell::RefCell,
|
||||
// env, fs,
|
||||
// path::PathBuf,
|
||||
// sync::atomic::{AtomicUsize, Ordering},
|
||||
// };
|
||||
//
|
||||
// const PACKAGE_TEST_DIRECTORY: &str = "package-testing";
|
||||
//
|
||||
// thread_local! {
|
||||
// /// Establish a test id for each test.
|
||||
// pub static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
|
||||
// }
|
||||
//
|
||||
// lazy_static! {
|
||||
// /// Create a testing directory for packages in `target/`
|
||||
// pub static ref TEST_DIR: PathBuf = {
|
||||
// let mut path = env::current_exe().unwrap();
|
||||
// path.pop(); // Remove executable name
|
||||
// path.pop(); // Remove 'debug'
|
||||
//
|
||||
// // Attempt to point at the `target` directory
|
||||
// if path.file_name().and_then(|s| s.to_str()) != Some("target") {
|
||||
// path.pop();
|
||||
// }
|
||||
//
|
||||
// path.push(PACKAGE_TEST_DIRECTORY);
|
||||
// fs::create_dir_all(&path).unwrap();
|
||||
//
|
||||
// path
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// /// Create a new directory for each test based on the ID of the test.
|
||||
// pub(crate) fn test_dir() -> PathBuf {
|
||||
// static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
//
|
||||
// let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
// TEST_ID.with(|n| *n.borrow_mut() = Some(id));
|
||||
//
|
||||
// let path: PathBuf = TEST_DIR.join(&format!("t{}", id));
|
||||
//
|
||||
// if path.exists() {
|
||||
// if let Err(e) = fs::remove_dir_all(&path) {
|
||||
// panic!("failed to remove {:?}: {:?}", &path, e)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fs::create_dir_all(&path).unwrap();
|
||||
//
|
||||
// path
|
||||
// }
|
||||
|
@ -14,7 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::config::Config;
|
||||
use leo_errors::{CliError, Result};
|
||||
|
||||
use std::fmt::Write as _;
|
||||
@ -91,24 +90,13 @@ impl Updater {
|
||||
|
||||
/// Display the CLI message, if the Leo configuration allows.
|
||||
pub fn print_cli() {
|
||||
let config = Config::read_config().unwrap();
|
||||
// If the auto update configuration is off, notify the user to update leo.
|
||||
if let Ok(latest_version) = Self::update_available() {
|
||||
let mut message = "🟢 A new version is available! Run".bold().green().to_string();
|
||||
message += &" `leo update` ".bold().white();
|
||||
message += &format!("to update to v{}.", latest_version).bold().green();
|
||||
|
||||
if config.update.automatic {
|
||||
// If the auto update configuration is on, attempt to update the version.
|
||||
if let Ok(status) = Self::update_to_latest_release(false) {
|
||||
if status.updated() {
|
||||
tracing::info!("Successfully updated to {}", status.version());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the auto update configuration is off, notify the user to update leo.
|
||||
if let Ok(latest_version) = Self::update_available() {
|
||||
let mut message = "🟢 A new version is available! Run".bold().green().to_string();
|
||||
message += &" `leo update` ".bold().white();
|
||||
message += &format!("to update to v{}.", latest_version).bold().green();
|
||||
|
||||
tracing::info!("\n{}\n", message);
|
||||
}
|
||||
tracing::info!("\n{}\n", message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user