Skip to content

Commit

Permalink
Improved run.rs (#197)
Browse files Browse the repository at this point in the history
* improved run.rs

* fix
  • Loading branch information
yulesa authored Nov 24, 2024
1 parent d3430c6 commit dbc6deb
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ target
*.parquet_tmp
*.json
*.json_tmp
*.env
*._tmp
TODO.md
graveyard
Expand Down
195 changes: 146 additions & 49 deletions crates/cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,110 @@ use colored::Colorize;
use cryo_freeze::{err, CollectError, ExecutionEnv, FreezeSummary};
use std::{sync::Arc, time::SystemTime};

/// run cli
/// Entry point to run the CLI application.
pub async fn run(args: args::Args) -> Result<Option<FreezeSummary>, CollectError> {
// handle subcommands
if args.datatype.first() == Some(&"help".to_string()) {
return handle_help_subcommands(args).await
if is_help_command(&args) {
return handle_help_subcommands(args);
}

let cryo_dir: std::path::PathBuf = args.output_dir.clone().into();
let cryo_dir = cryo_dir.join(".cryo");
let cryo_dir = build_cryo_directory(&args.output_dir.clone().into());

// remember previous command

let args = if args.datatype.is_empty() {
let remembered = remember::load_remembered_command(cryo_dir.clone())?;
if remembered.cryo_version != cryo_freeze::CRYO_VERSION {
eprintln!("remembered command comes from different cryo version, proceed with caution");
eprintln!();
};
println!(
"{} {} {}",
"remembering previous command:".truecolor(170, 170, 170),
"cryo".bold().white(),
remembered.command.into_iter().skip(1).collect::<Vec<_>>().join(" ").white().bold()
);
println!();
args.merge_with_precedence(remembered.args)
load_or_remember_command(args, &cryo_dir)?
} else {
args
};

// remember current command
if args.remember {
println!("remembering this command for future use");
println!();
println!("remembering this command for future use\n");
remember::save_remembered_command(cryo_dir, &args)?;
}

// handle regular flow
run_freeze_process(args).await
}

/// Check if the command is a help command.
fn is_help_command(args: &args::Args) -> bool {
args.datatype.first() == Some(&"help".to_string())
}

/// Build the cryo directory path.
fn build_cryo_directory(output_dir: &std::path::PathBuf) -> std::path::PathBuf {
output_dir.join(".cryo")
}

/// Load a previously remembered command or return the current args.
fn load_or_remember_command(
mut args: args::Args,
cryo_dir: &std::path::PathBuf,
) -> Result<args::Args, CollectError> {
let remembered = remember::load_remembered_command(cryo_dir.clone())?;
// Warn if the remembered command comes from a different Cryo version.
if remembered.cryo_version != cryo_freeze::CRYO_VERSION {
eprintln!("remembered command comes from a different Cryo version, proceed with caution\n");
}
print_remembered_command(&remembered.command);
args = args.merge_with_precedence(remembered.args);
Ok(args)
}


/// Print the remembered command to the console.
fn print_remembered_command(command: &[String]) {
println!(
"{} {} {}",
"remembering previous command:".truecolor(170, 170, 170),
"cryo".bold().white(),
command
.iter()
.skip(1)
.cloned()
.collect::<Vec<_>>()
.join(" ")
.white()
.bold()
);
println!();
}

/// Run the main freezing process with the provided arguments.
async fn run_freeze_process(
args: args::Args,
) -> Result<Option<FreezeSummary>, CollectError> {
let t_start_parse = Some(SystemTime::now());
let (query, source, sink, env) = match parse::parse_args(&args).await {
Ok(opts) => opts,
Err(e) => return Err(e.into()),
};
let (query, source, sink, env) = parse::parse_args(&args).await?;

let source = Arc::new(source);
let env = ExecutionEnv { t_start_parse, ..env };
let env = env.set_start_time();
let env = ExecutionEnv {t_start_parse, ..env}
.set_start_time();

cryo_freeze::freeze(&query, &source, &sink, &env).await
}

async fn handle_help_subcommands(args: args::Args) -> Result<Option<FreezeSummary>, CollectError> {
if args.datatype.len() == 1 {
args::Args::parse_from(vec!["cryo", "-h"]);
} else if args.datatype.len() == 2 && args.datatype[1] == "syntax" {
/// Handle help-related subcommands.
fn handle_help_subcommands(args: args::Args) -> Result<Option<FreezeSummary>, CollectError> {
match args.datatype.len() {
// if only "help" is provided, print general help
1 => print_general_help(),
// if "syntax help" is provided, print syntax help
2 if args.datatype[1] == "syntax" => print_syntax_help(),
// if "help datasets" is provided, print dataset information
2 if args.datatype.contains(&"datasets".to_string()) => cryo_freeze::print_all_datasets(),
// if "help <datatype>" is provided, print detailed help
_ => handle_detailed_help(args)?,
}
Ok(None)
}

/// Print general help for the CLI tool.
fn print_general_help() {
args::Args::parse_from(vec!["cryo", "-h"]);
}

/// Print syntax help for block and transaction specification.
fn print_syntax_help() {
let content = cstr!(
r#"<white><bold>Block specification syntax</bold></white>
- can use numbers <white><bold>--blocks 5000 6000 7000</bold></white>
Expand All @@ -79,22 +130,68 @@ async fn handle_help_subcommands(args: args::Args) -> Result<Option<FreezeSummar
- can use multiple parquet files <white><bold>--txs ./path/to/ethereum__logs*.parquet</bold></white>"#
);
println!("{}", content);
} else if args.datatype.len() == 2 && args.datatype.contains(&"datasets".to_string()) {
cryo_freeze::print_all_datasets();
} else {
let args = args::Args { datatype: args.datatype[1..].to_vec(), ..args };
let (datatypes, schemas) = super::parse::schemas::parse_schemas(&args)?;
for datatype in datatypes.into_iter() {
if schemas.len() > 1 {
println!();
println!();
};
if let Some(schema) = schemas.get(&datatype) {
cryo_freeze::print_dataset_info(datatype, schema);
} else {
return Err(err(format!("missing schema for datatype: {:?}", datatype).as_str()))
}
}

/// Handle detailed help by parsing schemas and printing dataset information.
fn handle_detailed_help(args: args::Args) -> Result<(), CollectError> {
let args = args::Args {
datatype: args.datatype[1..].to_vec(),
..args
};
let (datatypes, schemas) = super::parse::schemas::parse_schemas(&args)?;

for datatype in datatypes.into_iter() {
if schemas.len() > 1 {
println!("\n");
}
if let Some(schema) = schemas.get(&datatype) {
cryo_freeze::print_dataset_info(datatype, schema);
} else {
return Err(err(format!("missing schema for datatype: {:?}", datatype).as_str()));
}
}
Ok(None)

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
use crate::args::Args;

#[test]
fn test_handle_help_subcommands_general_help() {
let args = Args {
datatype: vec!["help".to_string()],
..Default::default()
};

let result = handle_help_subcommands(args);

assert!(result.is_ok());
}

#[test]
fn test_handle_help_subcommands_syntax_help() {
let args = Args {
datatype: vec!["help".to_string(), "syntax".to_string()],
..Default::default()
};

let result = handle_help_subcommands(args);

assert!(result.is_ok());
}

#[test]
fn test_handle_help_subcommands_datasets_help() {
let args = Args {
datatype: vec!["help".to_string(), "datasets".to_string()],
..Default::default()
};

let result = handle_help_subcommands(args);

assert!(result.is_ok());
}
}

0 comments on commit dbc6deb

Please sign in to comment.