Skip to content

Commit

Permalink
Refactor project generation
Browse files Browse the repository at this point in the history
  • Loading branch information
kubaplas committed Jan 10, 2024
1 parent c9c222a commit 25cbe37
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 291 deletions.
207 changes: 196 additions & 11 deletions src/actions/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,203 @@
use std::path::PathBuf;

use cargo_generate::{GenerateArgs, TemplatePath, Vcs};
use cargo_toml::{Dependency, DependencyDetail};
use chrono::Utc;
use ureq::serde_json;

use crate::{
cli::InitCommand,
command::replace_in_file,
consts::{ODRA_GITHUB_API_DATA, ODRA_TEMPLATE_GH_REPO},
errors::Error,
log,
paths,
project::OdraLocation,
};

/// InitAction configuration.
#[derive(Clone)]
pub struct InitAction {
pub project_name: String,
pub generate: bool,
pub init: bool,
pub repo_uri: String,
pub source: Option<String>,
pub workspace: bool,
pub template: String,
pub current_dir: PathBuf,
}
pub struct InitAction {}

/// InitAction implementation.
impl InitAction {}
impl InitAction {
pub fn generate_project(init_command: InitCommand, current_dir: PathBuf, init: bool) {
if init {
Self::assert_dir_is_empty(current_dir.clone());
}

log::info("Generating a new project...");

let odra_location = Self::odra_location(init_command.source);

let template_path = match odra_location.clone() {
OdraLocation::Local(local_path) => TemplatePath {
auto_path: Some(local_path.as_os_str().to_str().unwrap().to_string()),
subfolder: Some(format!("templates/{}", init_command.template)),
test: false,
git: None,
branch: None,
tag: None,
path: None,
favorite: None,
},
OdraLocation::Remote(repo, branch) => TemplatePath {
auto_path: Some(repo),
subfolder: Some(format!("templates/{}", init_command.template)),
test: false,
git: None,
branch,
tag: None,
path: None,
favorite: None,
},
OdraLocation::CratesIO(version) => TemplatePath {
auto_path: Some(ODRA_TEMPLATE_GH_REPO.to_string()),
subfolder: Some(format!("templates/{}", init_command.template)),
test: false,
git: None,
branch: Some(format!("release/{}", version)),
tag: None,
path: None,
favorite: None,
},
};

cargo_generate::generate(GenerateArgs {
template_path,
list_favorites: false,
name: Some(paths::to_snake_case(&init_command.name)),
force: true,
verbose: false,
template_values_file: None,
silent: false,
config: None,
vcs: Some(Vcs::Git),
lib: false,
bin: false,
ssh_identity: None,
define: vec![format!("date={}", Utc::now().format("%Y-%m-%d"))],
init,
destination: None,
force_git_init: false,
allow_commands: false,
overwrite: false,
other_args: None,
})
.unwrap_or_else(|e| {
Error::FailedToGenerateProjectFromTemplate(e.to_string()).print_and_die();
});

let cargo_toml_path = match init {
true => {
let mut path = current_dir;
path.push("Cargo.toml");
path
}
false => {
let mut path = current_dir;
path.push(paths::to_snake_case(&init_command.name));
path.push("Cargo.toml");
path
}
};

replace_in_file(
cargo_toml_path,
"#odra_dependency",
format!(
"odra = {{ {} }}",
toml::to_string(&Self::odra_project_dependency(odra_location, init))
.unwrap()
.trim_end()
.replace('\n', ", ")
)
.as_str(),
);

log::info("Done!");
}
fn assert_dir_is_empty(dir: PathBuf) {
if dir.read_dir().unwrap().next().is_some() {
Error::CurrentDirIsNotEmpty.print_and_die();
}
}

fn odra_location(source: Option<String>) -> OdraLocation {
let source = if let Some(source) = source {
source
} else {
Self::odra_latest_version()
};

// location on disk
let local = PathBuf::from(&source);
if local.exists() {
OdraLocation::Local(local)
} else {
// version
let version_regex = regex::Regex::new(r"^\d+\.\d+\.\d+$").unwrap();
if version_regex.is_match(&source) {
OdraLocation::Remote(
ODRA_TEMPLATE_GH_REPO.to_string(),
Some(format!("release/{}", source)),
)
} else {
// branch
OdraLocation::Remote(ODRA_TEMPLATE_GH_REPO.to_string(), Some(source))
}
}
}
fn odra_latest_version() -> String {
let response: serde_json::Value = ureq::get(ODRA_GITHUB_API_DATA)
.call()
.unwrap_or_else(|_| {
Error::FailedToFetchTemplate(ODRA_GITHUB_API_DATA.to_string()).print_and_die()
})
.into_json()
.unwrap_or_else(|_| {
Error::FailedToParseTemplate(ODRA_GITHUB_API_DATA.to_string()).print_and_die()
});
response["tag_name"].as_str().unwrap().to_string()
}

fn odra_project_dependency(odra_location: OdraLocation, init: bool) -> Dependency {
let (version, path, git, branch) = match odra_location {
OdraLocation::Local(path) => {
let path = match init {
true => path,
false => PathBuf::from("..").join(path),
};
let path = path
.join("odra")
.into_os_string()
.to_str()
.unwrap()
.to_string();
(None, Some(path), None, None)
}
OdraLocation::Remote(repo, branch) => match branch {
None => (Some(Self::odra_latest_version()), None, None, None),
Some(branch) => (None, None, Some(repo), Some(branch)),
},
OdraLocation::CratesIO(version) => (Some(version), None, None, None),
};

Dependency::Detailed(DependencyDetail {
version,
registry: None,
registry_index: None,
path,
inherited: false,
git,
branch,
tag: None,
rev: None,
features: vec![],
optional: false,
default_features: false,
package: None,
})
}
}
41 changes: 17 additions & 24 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ use std::env;
use clap::{CommandFactory, Parser, Subcommand};

use crate::{
actions::{clean::clean_action, init::InitAction, update::update_action},
actions::{
build::BuildAction,
clean::clean_action,
generate::GenerateAction,
init::InitAction,
test::TestAction,
update::update_action,
},
consts,
errors::Error,
project::Project,
Expand Down Expand Up @@ -131,37 +138,23 @@ pub fn make_action() {
.unwrap_or_else(|_| Error::CouldNotDetermineCurrentDirectory.print_and_die());
match args.subcommand {
OdraSubcommand::Build(build) => {
Project::detect(current_dir).build(build.contracts_names);
let project = Project::detect(current_dir);
BuildAction::new(&project, build.contracts_names).build();
}
OdraSubcommand::Test(test) => {
Project::detect(current_dir).test(test);
let project = Project::detect(current_dir);
TestAction::new(&project, test.backend, test.args, test.skip_build).test();
}
OdraSubcommand::Generate(generate) => {
Project::detect(current_dir).generate(generate);
let project = Project::detect(current_dir);
GenerateAction::new(&project, generate.contract_name, generate.module)
.generate_contract();
}
OdraSubcommand::New(init) => {
Project::init(InitAction {
project_name: init.name,
generate: true,
init: false,
repo_uri: init.repo_uri,
source: init.source,
workspace: false,
template: init.template,
current_dir,
});
InitAction::generate_project(init, current_dir, false);
}
OdraSubcommand::Init(init) => {
Project::init(InitAction {
project_name: init.name,
generate: true,
init: true,
repo_uri: init.repo_uri,
source: init.source,
workspace: false,
template: init.template,
current_dir,
});
InitAction::generate_project(init, current_dir, true);
}
OdraSubcommand::Clean(_) => {
let project = Project::detect(current_dir);
Expand Down
Loading

0 comments on commit 25cbe37

Please sign in to comment.