mirror of
https://github.com/ProvableHQ/leo.git
synced 2025-01-03 07:41:48 +03:00
finalizes import stabilization
- temporarily disables leo add and leo rm - lock file is parsed by leo build and used - error messages improved for some cases - fetch test is added and improved
This commit is contained in:
parent
6be4860513
commit
c36be2c745
@ -145,18 +145,18 @@ jobs:
|
||||
export LEO=/home/circleci/project/project/bin/leo
|
||||
./project/.circleci/leo-setup.sh
|
||||
|
||||
leo-add-remove:
|
||||
docker:
|
||||
- image: cimg/rust:1.52.1
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /home/circleci/project/
|
||||
- run:
|
||||
name: leo add & remove
|
||||
command: |
|
||||
export LEO=/home/circleci/project/project/bin/leo
|
||||
./project/.circleci/leo-add-remove.sh
|
||||
# leo-add-remove:
|
||||
# docker:
|
||||
# - image: cimg/rust:1.52.1
|
||||
# resource_class: xlarge
|
||||
# steps:
|
||||
# - attach_workspace:
|
||||
# at: /home/circleci/project/
|
||||
# - run:
|
||||
# name: leo add & remove
|
||||
# command: |
|
||||
# export LEO=/home/circleci/project/project/bin/leo
|
||||
# ./project/.circleci/leo-add-remove.sh
|
||||
|
||||
leo-check-constraints:
|
||||
docker:
|
||||
|
@ -135,6 +135,11 @@ impl Command for Build {
|
||||
let package_name = manifest.get_package_name();
|
||||
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(anyhow!("Dependencies are not installed, please run `leo fetch` first"));
|
||||
}
|
||||
|
||||
// Sanitize the package path to the root directory.
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
@ -175,6 +180,14 @@ impl Command for Build {
|
||||
);
|
||||
}
|
||||
|
||||
let imports_map = if context.lock_file_exists()? {
|
||||
context.lock_file()?.to_hashmap()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
dbg!(&imports_map);
|
||||
|
||||
// Load the program at `main_file_path`
|
||||
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_input(
|
||||
package_name.clone(),
|
||||
|
@ -14,6 +14,10 @@
|
||||
// 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/>.
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// COMMAND TEMPORARILY DISABLED
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
use crate::{api::Fetch, commands::Command, context::Context};
|
||||
use leo_package::imports::{ImportsDirectory, IMPORTS_DIRECTORY_NAME};
|
||||
|
||||
|
@ -59,6 +59,7 @@ impl Command for Fetch {
|
||||
.map_err(|_| anyhow!("Package Manifest not found"))?
|
||||
.get_package_dependencies();
|
||||
|
||||
// If program has no dependencies in the Leo.toml, exit with success.
|
||||
let dependencies = match dependencies {
|
||||
Some(dependencies) => dependencies,
|
||||
None => return Ok(()),
|
||||
@ -77,6 +78,8 @@ impl Command for Fetch {
|
||||
}
|
||||
|
||||
impl Fetch {
|
||||
/// Pulls dependencies and fills in the lock file. Also checks for
|
||||
/// recursive dependencies with dependency tree.
|
||||
fn add_dependencies(
|
||||
&self,
|
||||
context: Context,
|
||||
@ -86,8 +89,11 @@ impl Fetch {
|
||||
) -> Result<()> {
|
||||
// Go through each dependency in Leo.toml and add it to the imports.
|
||||
// While adding, pull dependencies of this package as well and check for recursion.
|
||||
for (_import_name, dependency) in dependencies.into_iter() {
|
||||
let mut package = Package::from(dependency);
|
||||
for (import_name, dependency) in dependencies.into_iter() {
|
||||
let mut package = Package::from(&dependency);
|
||||
package.import_name = Some(import_name);
|
||||
|
||||
// Pull the dependency first.
|
||||
let path = Add::new(
|
||||
None,
|
||||
Some(package.author.clone()),
|
||||
@ -112,7 +118,11 @@ impl Fetch {
|
||||
}
|
||||
|
||||
// Check imported dependency's dependencies.
|
||||
let imported_dependencies = create_context(path, None)?.manifest()?.get_package_dependencies();
|
||||
let imported_dependencies = create_context(path, None)?
|
||||
.manifest()
|
||||
.map_err(|_| anyhow!("Unable to parse imported dependency's manifest"))?
|
||||
.get_package_dependencies();
|
||||
|
||||
if let Some(dependencies) = imported_dependencies {
|
||||
if !dependencies.is_empty() {
|
||||
// Fill in the lock file with imported dependency and information about its dependencies.
|
||||
|
@ -14,6 +14,10 @@
|
||||
// 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/>.
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// COMMAND TEMPORARILY DISABLED
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
use crate::{commands::Command, context::Context};
|
||||
use leo_package::LeoPackage;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{api::Api, config};
|
||||
use leo_package::root::Manifest;
|
||||
use leo_package::root::{LockFile, Manifest};
|
||||
|
||||
use anyhow::Result;
|
||||
use std::{convert::TryFrom, env::current_dir, path::PathBuf};
|
||||
@ -41,10 +41,20 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get package manifest for current context
|
||||
/// Get package manifest for current context.
|
||||
pub fn manifest(&self) -> Result<Manifest> {
|
||||
Ok(Manifest::try_from(self.dir()?.as_path())?)
|
||||
}
|
||||
|
||||
/// Get lock file for current context.
|
||||
pub fn lock_file(&self) -> Result<LockFile> {
|
||||
Ok(LockFile::try_from(self.dir()?.as_path())?)
|
||||
}
|
||||
|
||||
/// Check if lock file exists.
|
||||
pub fn lock_file_exists(&self) -> Result<bool> {
|
||||
Ok(LockFile::exists_at(&self.dir()?))
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new context for the current directory.
|
||||
|
33
leo/main.rs
33
leo/main.rs
@ -22,7 +22,7 @@ pub mod logger;
|
||||
pub mod updater;
|
||||
|
||||
use commands::{
|
||||
package::{Add, Clone, Fetch, Login, Logout, Publish, Remove},
|
||||
package::{Clone, Fetch, Login, Logout, Publish},
|
||||
Build,
|
||||
Clean,
|
||||
Command,
|
||||
@ -131,13 +131,12 @@ enum CommandOpts {
|
||||
command: Test,
|
||||
},
|
||||
|
||||
#[structopt(about = "Import a package from the Aleo Package Manager")]
|
||||
Add {
|
||||
#[structopt(flatten)]
|
||||
command: Add,
|
||||
},
|
||||
|
||||
#[structopt(about = "Install dependencies for this program")]
|
||||
// #[structopt(about = "Import a package from the Aleo Package Manager")]
|
||||
// Add {
|
||||
// #[structopt(flatten)]
|
||||
// command: Add,
|
||||
// },
|
||||
#[structopt(about = "Pull dependencies from Aleo Package Manager")]
|
||||
Fetch {
|
||||
#[structopt(flatten)]
|
||||
command: Fetch,
|
||||
@ -167,12 +166,11 @@ enum CommandOpts {
|
||||
command: Publish,
|
||||
},
|
||||
|
||||
#[structopt(about = "Uninstall a package from the current package")]
|
||||
Remove {
|
||||
#[structopt(flatten)]
|
||||
command: Remove,
|
||||
},
|
||||
|
||||
// #[structopt(about = "Uninstall a package from the current package")]
|
||||
// Remove {
|
||||
// #[structopt(flatten)]
|
||||
// command: Remove,
|
||||
// },
|
||||
#[structopt(about = "Lints the Leo files in the package (*)")]
|
||||
Lint {
|
||||
#[structopt(flatten)]
|
||||
@ -219,14 +217,13 @@ fn run_with_args(opt: Opt) -> Result<()> {
|
||||
CommandOpts::Watch { command } => command.try_execute(context),
|
||||
CommandOpts::Update { command } => command.try_execute(context),
|
||||
|
||||
CommandOpts::Add { command } => command.try_execute(context),
|
||||
// CommandOpts::Add { command } => command.try_execute(context),
|
||||
CommandOpts::Fetch { command } => command.try_execute(context),
|
||||
CommandOpts::Clone { command } => command.try_execute(context),
|
||||
CommandOpts::Login { command } => command.try_execute(context),
|
||||
CommandOpts::Logout { command } => command.try_execute(context),
|
||||
CommandOpts::Publish { command } => command.try_execute(context),
|
||||
CommandOpts::Remove { command } => command.try_execute(context),
|
||||
|
||||
// CommandOpts::Remove { command } => command.try_execute(context),
|
||||
CommandOpts::Lint { command } => command.try_execute(context),
|
||||
CommandOpts::Deploy { command } => command.try_execute(context),
|
||||
}
|
||||
@ -425,6 +422,7 @@ mod cli_tests {
|
||||
.open(path.join("install/Leo.toml"))
|
||||
.unwrap();
|
||||
|
||||
assert!(run_cmd("leo fetch", install_path).is_ok());
|
||||
assert!(
|
||||
file.write_all(
|
||||
br#"
|
||||
@ -435,5 +433,6 @@ mod cli_tests {
|
||||
);
|
||||
|
||||
assert!(run_cmd("leo fetch", install_path).is_ok());
|
||||
assert!(run_cmd("leo build", install_path).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -45,3 +45,9 @@ impl From<toml::ser::Error> for LockFileError {
|
||||
LockFileError::Crate("toml", error.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<toml::de::Error> for LockFileError {
|
||||
fn from(error: toml::de::Error) -> Self {
|
||||
LockFileError::Crate("toml", error.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,14 @@
|
||||
use crate::{errors::LockFileError, root::Dependency};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{borrow::Cow, collections::HashMap, fs::File, io::Write, path::Path};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
convert::TryFrom,
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
pub const LOCKFILE_FILENAME: &str = "Leo.lock";
|
||||
|
||||
@ -31,10 +38,11 @@ pub struct LockFile {
|
||||
/// Single dependency record.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Package {
|
||||
// pub import_name: String,
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub author: String,
|
||||
pub import_name: Option<String>,
|
||||
#[serde(skip_serializing_if = "HashMap::is_empty", default)]
|
||||
pub dependencies: HashMap<String, String>,
|
||||
}
|
||||
|
||||
@ -43,6 +51,15 @@ impl LockFile {
|
||||
LockFile { package: vec![] }
|
||||
}
|
||||
|
||||
/// Check if LockFile exists in a directory.
|
||||
pub fn exists_at(path: &Path) -> bool {
|
||||
let mut path = Cow::from(path);
|
||||
if path.is_dir() {
|
||||
path.to_mut().push(LOCKFILE_FILENAME);
|
||||
}
|
||||
path.exists()
|
||||
}
|
||||
|
||||
/// Add Package record to the lock file. Chainable.
|
||||
pub fn add_package(&mut self, package: Package) -> &mut Self {
|
||||
self.package.push(package);
|
||||
@ -53,6 +70,18 @@ impl LockFile {
|
||||
Ok(toml::to_string(self)?)
|
||||
}
|
||||
|
||||
pub fn to_hashmap(&self) -> HashMap<String, String> {
|
||||
let mut result = HashMap::new();
|
||||
for package in self.package.iter() {
|
||||
match &package.import_name {
|
||||
Some(name) => result.insert(name.clone(), package.to_identifier()),
|
||||
None => result.insert(package.name.clone(), package.to_identifier()),
|
||||
};
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Write Leo.lock to the given location.
|
||||
pub fn write_to(self, path: &Path) -> Result<(), LockFileError> {
|
||||
let mut path = Cow::from(path);
|
||||
@ -66,29 +95,53 @@ impl LockFile {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Path> for LockFile {
|
||||
type Error = LockFileError;
|
||||
|
||||
fn try_from(path: &Path) -> Result<Self, Self::Error> {
|
||||
let mut path = Cow::from(path);
|
||||
if path.is_dir() {
|
||||
path.to_mut().push(LOCKFILE_FILENAME);
|
||||
}
|
||||
|
||||
let mut file = File::open(path.clone()).map_err(|error| LockFileError::Opening(LOCKFILE_FILENAME, error))?;
|
||||
let size = file
|
||||
.metadata()
|
||||
.map_err(|error| LockFileError::Metadata(LOCKFILE_FILENAME, error))?
|
||||
.len() as usize;
|
||||
|
||||
let mut buffer = String::with_capacity(size);
|
||||
file.read_to_string(&mut buffer)
|
||||
.map_err(|error| LockFileError::Reading(LOCKFILE_FILENAME, error))?;
|
||||
|
||||
toml::from_str(&buffer).map_err(|error| LockFileError::Parsing(LOCKFILE_FILENAME, error))
|
||||
}
|
||||
}
|
||||
|
||||
impl Package {
|
||||
/// Fill dependencies from Leo Manifest data.
|
||||
pub fn add_dependencies(&mut self, dependencies: &HashMap<String, Dependency>) {
|
||||
for (import_name, dependency) in dependencies.iter() {
|
||||
self.dependencies
|
||||
.insert(import_name.clone(), dependency.package.clone());
|
||||
.insert(import_name.clone(), Package::from(dependency).to_identifier());
|
||||
}
|
||||
}
|
||||
|
||||
/// Form an path identifier for a package. It is the path under which package is stored
|
||||
/// inside the `imports/` directory.
|
||||
pub fn to_identifier(&self) -> String {
|
||||
format!("{}-{}@{}", self.author, self.name, self.version)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dependency> for Package {
|
||||
fn from(dependency: Dependency) -> Package {
|
||||
let Dependency {
|
||||
author,
|
||||
version,
|
||||
package,
|
||||
} = dependency;
|
||||
|
||||
impl From<&Dependency> for Package {
|
||||
fn from(dependency: &Dependency) -> Package {
|
||||
Package {
|
||||
name: package,
|
||||
author,
|
||||
version,
|
||||
name: dependency.package.clone(),
|
||||
author: dependency.author.clone(),
|
||||
version: dependency.version.clone(),
|
||||
dependencies: Default::default(),
|
||||
import_name: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user