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