impl zip file struct

This commit is contained in:
collin 2020-06-26 00:57:46 -07:00
parent 6662b6261f
commit d9b5c15d73
8 changed files with 165 additions and 208 deletions

View File

@ -10,7 +10,6 @@ use leo_compiler::{compiler::Compiler, group::edwards_bls12::EdwardsGroupType};
use snarkos_algorithms::snark::KeypairAssembly;
use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq};
use crate::files::BytesFile;
use clap::ArgMatches;
use std::{convert::TryFrom, env::current_dir};
@ -60,30 +59,8 @@ impl CLI for BuildCommand {
main_file_path.push(SOURCE_DIRECTORY_NAME);
main_file_path.push(MAIN_FILE_NAME);
// Check if the program bytes exist
let existing_bytes = BytesFile::new(&package_name).exists_at(&path);
let program = if existing_bytes {
// Load the program ast from stored bytes
let bytes = BytesFile::new(&package_name).read_from(&path)?;
let mut program = Compiler::<Fq, EdwardsGroupType>::from_bytes(bytes.as_slice())?;
program.set_path(main_file_path.clone());
program
} else {
// Load the program at `main_file_path`
let program =
Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
// Store the program ast as bytes
let bytes = program.to_bytes()?;
BytesFile::new(&package_name).write_to(&path, bytes)?;
program
};
// Load the program at `main_file_path`
let program = Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
// Compute the current program checksum
let program_checksum = program.checksum()?;

View File

@ -2,29 +2,12 @@ use crate::{
cli::*,
cli_types::*,
commands::BuildCommand,
directories::{INPUTS_DIRECTORY_NAME, OUTPUTS_DIRECTORY_NAME},
errors::CLIError,
files::{
Manifest,
BYTES_FILE_EXTENSION,
CHECKSUM_FILE_EXTENSION,
INPUTS_FILE_EXTENSION,
PROOF_FILE_EXTENSION,
PROVING_KEY_FILE_EXTENSION,
VERIFICATION_KEY_FILE_EXTENSION,
},
files::{Manifest, ZipFile},
};
use clap::ArgMatches;
use std::{
convert::TryFrom,
env::current_dir,
fs::File,
io::{Read, Write},
path::{Path, PathBuf},
};
use walkdir::WalkDir;
use zip::write::{FileOptions, ZipWriter};
use std::{convert::TryFrom, env::current_dir};
#[derive(Debug)]
pub struct PublishCommand;
@ -50,81 +33,17 @@ impl CLI for PublishCommand {
let (_program, _checksum_differs) = BuildCommand::output(options)?;
// Get the package name
let src_dir = current_dir()?;
// Build walkdir iterator from current package
let walkdir = WalkDir::new(src_dir.clone());
let path = current_dir()?;
let package_name = Manifest::try_from(&path)?.get_package_name();
// Create zip file
let package_name = Manifest::try_from(&src_dir)?.get_package_name();
let mut zip_file = src_dir.clone();
zip_file.push(PathBuf::from(format!("{}{}", package_name, ".zip".to_string())));
let file = &mut File::create(zip_file)?;
let mut zip = ZipWriter::new(file);
let zip_options = FileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o755);
// Walk through files in directory and write desired ones to the zip file
let mut buffer = Vec::new();
for entry in walkdir.into_iter().filter_map(|e| e.ok()) {
let path = entry.path();
let name = path.strip_prefix(src_dir.as_path()).unwrap();
// filter excluded paths
if is_excluded(name) {
continue;
}
// write file or directory
if path.is_file() {
log::info!("adding file {:?} as {:?}", path, name);
zip.start_file_from_path(name, zip_options)?;
let mut f = File::open(path)?;
f.read_to_end(&mut buffer)?;
zip.write_all(&*buffer)?;
buffer.clear();
} else if name.as_os_str().len() != 0 {
// Only if not root Avoids path spec / warning
// and mapname conversion failed error on unzip
log::info!("adding dir {:?} as {:?}", path, name);
zip.add_directory_from_path(name, zip_options)?;
}
let zip_file = ZipFile::new(&package_name);
if zip_file.exists_at(&path) {
log::info!("Existing package zip file found. Skipping compression.")
} else {
zip_file.write(&path)?;
}
zip.finish()?;
log::info!("zip file created");
Ok(())
}
}
fn is_excluded(path: &Path) -> bool {
// excluded directories: `/inputs`, `/outputs`
if path.ends_with(INPUTS_DIRECTORY_NAME.trim_end_matches("/"))
| path.ends_with(OUTPUTS_DIRECTORY_NAME.trim_end_matches("/"))
{
return true;
}
// excluded extensions: `.in`, `.bytes`, `lpk`, `lvk`, `.proof`, `.sum`
path.extension()
.map(|ext| {
if ext.eq(INPUTS_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(BYTES_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(PROVING_KEY_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(VERIFICATION_KEY_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(PROOF_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(CHECKSUM_FILE_EXTENSION.trim_start_matches("."))
| ext.eq("zip")
{
true
} else {
false
}
})
.unwrap_or(false)
}

View File

@ -1,15 +1,12 @@
use crate::errors::*;
use walkdir::Error as WalkDirError;
use zip::result::ZipError;
#[derive(Debug, Error)]
pub enum CLIError {
#[error("{}", _0)]
BuildError(BuildError),
#[error("{}", _0)]
BytesFileError(BytesFileError),
BytesFileError(ZipFileError),
#[error("{}: {}", _0, _1)]
Crate(&'static str, String),
@ -58,16 +55,10 @@ pub enum CLIError {
#[error("{}", _0)]
VerificationKeyFileError(VerificationKeyFileError),
#[error("{}", _0)]
WalkDirError(WalkDirError),
#[error("{}", _0)]
ZipError(ZipError),
}
impl From<BytesFileError> for CLIError {
fn from(error: BytesFileError) -> Self {
impl From<ZipFileError> for CLIError {
fn from(error: ZipFileError) -> Self {
log::error!("{}\n", error);
CLIError::BytesFileError(error)
}
@ -185,20 +176,6 @@ impl From<VerificationKeyFileError> for CLIError {
}
}
impl From<WalkDirError> for CLIError {
fn from(error: WalkDirError) -> Self {
log::error!("{}\n", error);
CLIError::WalkDirError(error)
}
}
impl From<ZipError> for CLIError {
fn from(error: ZipError) -> Self {
log::error!("{}\n", error);
CLIError::ZipError(error)
}
}
impl From<leo_compiler::errors::CompilerError> for CLIError {
fn from(error: leo_compiler::errors::CompilerError) -> Self {
log::error!("{}\n", error);

View File

@ -1,5 +1,5 @@
pub mod bytes;
pub use self::bytes::*;
pub mod zip;
pub use self::zip::*;
pub mod checksum;
pub use self::checksum::*;

View File

@ -1,7 +1,9 @@
use std::{io, path::PathBuf};
use walkdir::Error as WalkDirError;
use zip::result::ZipError;
#[derive(Debug, Error)]
pub enum BytesFileError {
pub enum ZipFileError {
#[error("{}: {}", _0, _1)]
Crate(&'static str, String),
@ -13,10 +15,16 @@ pub enum BytesFileError {
#[error("writing: {}", _0)]
Writing(io::Error),
#[error("{}", _0)]
WalkDirError(#[from] WalkDirError),
#[error("{}", _0)]
ZipError(#[from] ZipError),
}
impl From<std::io::Error> for BytesFileError {
impl From<std::io::Error> for ZipFileError {
fn from(error: std::io::Error) -> Self {
BytesFileError::Crate("std::io", format!("{}", error))
ZipFileError::Crate("std::io", format!("{}", error))
}
}

View File

@ -1,60 +0,0 @@
//! The program bytes file.
use crate::{directories::outputs::OUTPUTS_DIRECTORY_NAME, errors::BytesFileError};
use serde::Deserialize;
use std::{
fs::{self, File},
io::Write,
path::PathBuf,
};
pub static BYTES_FILE_EXTENSION: &str = ".bytes";
#[derive(Deserialize)]
pub struct BytesFile {
pub package_name: String,
}
impl BytesFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
}
pub fn exists_at(&self, path: &PathBuf) -> bool {
let path = self.setup_file_path(path);
path.exists()
}
/// Reads the program bytes from the given file path if it exists.
pub fn read_from(&self, path: &PathBuf) -> Result<Vec<u8>, BytesFileError> {
let path = self.setup_file_path(path);
Ok(fs::read(&path).map_err(|_| BytesFileError::FileReadError(path.clone()))?)
}
/// Writes the given program bytes to a file.
pub fn write_to(&self, path: &PathBuf, bytes: Vec<u8>) -> Result<(), BytesFileError> {
let path = self.setup_file_path(path);
let mut file = File::create(&path)?;
file.write_all(bytes.as_slice())?;
log::info!("program bytes stored to {:?}", path);
Ok(())
}
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
let mut path = path.to_owned();
if path.is_dir() {
if !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
}
path.push(PathBuf::from(format!("{}{}", self.package_name, BYTES_FILE_EXTENSION)));
}
path
}
}

View File

@ -1,5 +1,5 @@
pub mod bytes;
pub use self::bytes::*;
pub mod zip;
pub use self::zip::*;
pub mod checksum;
pub use self::checksum::*;

136
leo/files/zip.rs Normal file
View File

@ -0,0 +1,136 @@
//! The program package zip file.
use crate::{
directories::{INPUTS_DIRECTORY_NAME, OUTPUTS_DIRECTORY_NAME},
errors::ZipFileError,
files::{
CHECKSUM_FILE_EXTENSION,
INPUTS_FILE_EXTENSION,
PROOF_FILE_EXTENSION,
PROVING_KEY_FILE_EXTENSION,
VERIFICATION_KEY_FILE_EXTENSION,
},
};
use serde::Deserialize;
use std::{
fs::File,
io::{Read, Write},
path::{Path, PathBuf},
};
use walkdir::WalkDir;
use zip::write::{FileOptions, ZipWriter};
pub static ZIP_FILE_EXTENSION: &str = ".zip";
#[derive(Deserialize)]
pub struct ZipFile {
pub package_name: String,
}
impl ZipFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
}
pub fn exists_at(&self, path: &PathBuf) -> bool {
let path = self.setup_file_path(path);
path.exists()
}
// /// Reads the program bytes from the given file path if it exists.
// pub fn read_from(&self, path: &PathBuf) -> Result<Vec<u8>, ZipFileError> {
// let path = self.setup_file_path(path);
//
// Ok(fs::read(&path).map_err(|_| ZipFileError::FileReadError(path.clone()))?)
// }
/// Writes the current package contents to a zip file.
pub fn write(&self, src_dir: &PathBuf) -> Result<(), ZipFileError> {
// Build walkdir iterator from current package
let walkdir = WalkDir::new(src_dir.clone());
// Create zip file
let path = self.setup_file_path(src_dir);
let file = &mut File::create(&path)?;
let mut zip = ZipWriter::new(file);
let options = FileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o755);
// Walk through files in directory and write desired ones to the zip file
let mut buffer = Vec::new();
for entry in walkdir.into_iter().filter_map(|e| e.ok()) {
let path = entry.path();
let name = path.strip_prefix(src_dir.as_path()).unwrap();
// filter excluded paths
if is_excluded(name) {
continue;
}
// write file or directory
if path.is_file() {
log::info!("\tadding file {:?} as {:?}", path, name);
zip.start_file_from_path(name, options)?;
let mut f = File::open(path)?;
f.read_to_end(&mut buffer)?;
zip.write_all(&*buffer)?;
buffer.clear();
} else if name.as_os_str().len() != 0 {
// Only if not root Avoids path spec / warning
// and mapname conversion failed error on unzip
log::info!("\tadding dir {:?} as {:?}", path, name);
zip.add_directory_from_path(name, options)?;
}
}
zip.finish()?;
log::info!("Package zip file created successfully {:?}", path);
Ok(())
}
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
let mut path = path.to_owned();
if path.is_dir() {
if !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
}
path.push(PathBuf::from(format!("{}{}", self.package_name, ZIP_FILE_EXTENSION)));
}
path
}
}
fn is_excluded(path: &Path) -> bool {
// excluded directories: `/inputs`, `/outputs`
if path.ends_with(INPUTS_DIRECTORY_NAME.trim_end_matches("/"))
| path.ends_with(OUTPUTS_DIRECTORY_NAME.trim_end_matches("/"))
{
return true;
}
// excluded extensions: `.in`, `.bytes`, `lpk`, `lvk`, `.proof`, `.sum`
path.extension()
.map(|ext| {
if ext.eq(INPUTS_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(ZIP_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(PROVING_KEY_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(VERIFICATION_KEY_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(PROOF_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(CHECKSUM_FILE_EXTENSION.trim_start_matches("."))
| ext.eq(ZIP_FILE_EXTENSION.trim_start_matches("."))
{
true
} else {
false
}
})
.unwrap_or(false)
}