1mod authors;
2mod emoji;
3mod git;
4mod template;
5
6use crate::git::GitConfig;
7use crate::template::Name;
8use cargo;
9use console::style;
10use dialoguer::Input;
11use failure;
12use quicli::prelude::Error;
13use std::env;
14use std::path::PathBuf;
15use structopt::StructOpt;
16
17static EE_TEMPLATE: &str = "https://github.com/quilt/ease-template.git"; #[derive(StructOpt)]
20#[structopt(bin_name = "cargo")]
21pub enum Cli {
22 #[structopt(name = "ease")]
23 Ease(Args),
24}
25
26#[derive(Debug, StructOpt)]
27pub struct Args {
28 #[structopt(long = "branch")]
29 branch: Option<String>,
30 #[structopt(long = "name", short = "n")]
31 name: Option<String>,
32}
33
34pub fn prompt_for_name() -> Result<String, Error> {
35 let valid_ident = regex::Regex::new(r"^([a-zA-Z][a-zA-Z0-9_-]+)$")?;
36 let name = loop {
37 let name = Input::new(&format!(
38 "{} {}",
39 emoji::QUESTION,
40 style("Project Name").bold()
41 ))
42 .interact()?;
43 if valid_ident.is_match(&name) {
44 break name;
45 } else {
46 eprintln!(
47 "{} {} \"{}\" {}",
48 emoji::WARN,
49 style("Sorry,").bold().red(),
50 style(&name).bold().yellow(),
51 style("is not a valid crate name").bold().red()
52 );
53 }
54 };
55 Ok(name)
56}
57
58pub fn create(args: Args) -> Result<(), failure::Error> {
59 let name: &Name = &match &args.name {
60 Some(ref n) => Name::new(n),
61 None => Name::new(&prompt_for_name()?), };
63 let branch = args.branch.unwrap_or_else(|| "master".to_string()); let config = GitConfig::new(EE_TEMPLATE.to_string(), branch.clone())?;
65 if let Some(dir) = &create_project_dir(&name) {
66 match git::create(dir, config) {
67 Ok(_) => git::remove_history(dir).unwrap_or(apply_template(name, dir, &branch)?),
68 Err(e) => failure::bail!(
69 "{} {} {}",
70 emoji::ERROR,
71 style("Git Error:").bold().red(),
72 style(e).bold().red(),
73 ),
74 };
75 } else {
76 failure::bail!(
77 "{} {}",
78 emoji::ERROR,
79 style("Error: directory already exists!").bold().red(),
80 );
81 }
82 Ok(())
83}
84
85fn create_project_dir(name: &Name) -> Option<PathBuf> {
88 let dir_name = format!("{}",name.kebab_case()); let project_dir = env::current_dir()
90 .unwrap_or_else(|_e| ".".into())
91 .join(&dir_name);
92
93 println!(
94 "{} {} `{}`{}",
95 emoji::PICKAXE,
96 style("Creating project ").bold(),
97 style(&dir_name).bold().yellow(),
98 style("...").bold()
99 );
100
101 if project_dir.exists() {
102 None
103 } else {
104 Some(project_dir)
105 }
106}
107
108fn apply_template(name: &Name, dir: &PathBuf, branch: &str) -> Result<(), failure::Error> {
109 let template = template::substitute(name)?;
110 template::walk_dir(dir, template)?;
111 git::init(dir, branch)?;
112 let dir_string = dir.to_str().unwrap_or("");
113 println!(
114 "{} {} {} {}",
115 emoji::UNICORN,
116 style("Boom!").bold().green(),
117 style("New project created").bold(),
118 style(dir_string).underlined()
119 );
120 Ok(())
121}