update revs, improve error handling, remove unused code

This commit is contained in:
collin 2022-07-12 12:48:51 -07:00
parent f4a32331b7
commit dcd6501262
37 changed files with 775 additions and 1142 deletions

995
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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]

View File

@ -1,9 +0,0 @@
[project]
name = "hello"
version = "0.3.0"
description = "A minimal token program in Leo."
license = "LICENSE-MIT"
[remote]
author = "aleo"

View File

@ -1 +0,0 @@
# hello-world

View File

@ -1,3 +0,0 @@
[main]
r0: field = 1field;
r1: field = 1field;

View File

@ -1,6 +0,0 @@
{
"program": "hello.aleo",
"version": "0.0.0",
"description": "",
"license": "MIT"
}

View File

@ -1,3 +0,0 @@
function main(a: u32, b: u32) -> u32 {
return a + b;
}

View File

@ -1,3 +1,2 @@
build/
outputs/
/.leo
build/

View File

@ -0,0 +1,6 @@
# helloworld.aleo
## Build Guide
To compile this Aleo program, run:
```bash
aleo build
```

View File

@ -0,0 +1,4 @@
// The program input for helloworld/src/main.leo
[main]
a: u32 = 1u32;
b: u32 = 2u32;

View File

@ -1,4 +1,4 @@
program hello.aleo;
program helloworld.aleo;
function main:
input r0 as u32.private;

View File

@ -0,0 +1,10 @@
{
"program": "helloworld.aleo",
"version": "0.0.0",
"description": "",
"development": {
"private_key": "APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx",
"address": "aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau"
},
"license": "MIT"
}

View File

@ -0,0 +1,5 @@
// The 'helloworld' main function.
function main(a: u32, b: u32) -> u32 {
let c: u32 = a + b;
return c;
}

View File

@ -1,2 +1,2 @@
outputs/
/.leo
build/

View File

@ -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
View File

@ -0,0 +1,6 @@
# token.aleo
## Build Guide
To compile this Aleo program, run:
```bash
aleo build
```

View File

@ -1,3 +1,4 @@
// The program input for token/src/main.leo
[main]
[registers]
a: u32 = 1u32;
b: u32 = 2u32;

View File

@ -0,0 +1,10 @@
{
"program": "token.aleo",
"version": "0.0.0",
"description": "",
"development": {
"private_key": "APrivateKey1zkpBqRv2cwkSiR4hQ3Tb4AZFD3XzdwPqV9QsEykTKBV1YKT",
"address": "aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7"
},
"license": "MIT"
}

View File

@ -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

View File

@ -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)?;

View File

@ -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

View File

@ -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(())
}

View File

@ -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 })
}

View File

@ -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 {

View File

@ -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.

View File

@ -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;

View File

@ -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());
// }
// }

View File

@ -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
)

View File

@ -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) {

View File

@ -52,6 +52,6 @@ impl Gitignore {
}
fn template(&self) -> String {
"outputs/\n".to_string()
"outputs/\nbuild/\n".to_string()
}
}

View File

@ -16,6 +16,3 @@
pub mod gitignore;
pub use self::gitignore::*;
pub mod readme;
pub use self::readme::*;

View File

@ -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
)
}
}

View File

@ -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;

View File

@ -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
// }

View File

@ -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);
}
}
}