polyhorn_cli/commands/
init.rs

1use clap::Clap;
2use inflections::Inflect;
3use std::fs::{create_dir, read_dir, File};
4use std::io::{Error, Write};
5use std::process::Command;
6
7/// Creates a new Polyhorn app in the given directory.
8#[derive(Clap)]
9pub struct Init {
10    name: String,
11}
12
13impl Init {
14    /// Implementation of the platform-independent `polyhorn new` command.
15    pub fn main(&self) {
16        for entry in read_dir(std::env::current_dir().unwrap()).unwrap() {
17            match entry.unwrap().file_name().to_str().unwrap() {
18                ".polyhorn" => {}
19                name => {
20                    eprintln!(
21                        "error: can't initialize new Polyhorn project due to existing file: {:?}",
22                        name
23                    );
24                    std::process::abort();
25                }
26            }
27        }
28
29        self.write_assets().unwrap();
30        self.write_build().unwrap();
31        self.write_cargo().unwrap();
32        self.write_gitignore().unwrap();
33        self.write_polyhorn().unwrap();
34
35        let _ = create_dir("src");
36
37        self.write_lib().unwrap();
38
39        assert!(Command::new("cargo")
40            .arg("generate-lockfile")
41            .spawn()
42            .unwrap()
43            .wait()
44            .unwrap()
45            .success());
46    }
47
48    fn write_assets(&self) -> Result<(), Error> {
49        let _ = create_dir("assets");
50        File::create("assets/.gitkeep")?;
51
52        Ok(())
53    }
54
55    fn query_latest_version(&self) -> Result<String, Error> {
56        let output = Command::new("cargo")
57            .args(&["search", "polyhorn", "--limit", "1"])
58            .output()?;
59
60        assert!(output.status.success());
61
62        let output = String::from_utf8(output.stdout).unwrap();
63
64        assert!(output.starts_with("polyhorn = \""));
65
66        Ok(output.split('"').nth(1).unwrap().to_owned())
67    }
68
69    fn write_cargo(&self) -> Result<(), Error> {
70        let version = self.query_latest_version()?;
71
72        let mut file = File::create("Cargo.toml").unwrap();
73        file.write_fmt(format_args!(
74            include_str!("../../template/Cargo.toml.tmpl"),
75            name = self.name,
76            version = version,
77        ))
78    }
79
80    fn write_gitignore(&self) -> Result<(), Error> {
81        let mut file = File::create(".gitignore").unwrap();
82        file.write_fmt(format_args!(include_str!("../../template/.gitignore.tmpl"),))
83    }
84
85    fn write_polyhorn(&self) -> Result<(), Error> {
86        let mut file = File::create("Polyhorn.toml").unwrap();
87        file.write_fmt(format_args!(
88            include_str!("../../template/Polyhorn.toml.tmpl"),
89            title = self.name.to_title_case(),
90            pascal = self.name.to_pascal_case(),
91            snake = self.name.to_snake_case(),
92        ))
93    }
94
95    fn write_build(&self) -> Result<(), Error> {
96        let mut file = File::create("build.rs").unwrap();
97        file.write_fmt(format_args!(include_str!("../../template/build.rs.tmpl")))
98    }
99
100    fn write_lib(&self) -> Result<(), Error> {
101        let mut file = File::create("src/lib.rs").unwrap();
102        file.write_fmt(format_args!(include_str!("../../template/src/lib.rs.tmpl")))
103    }
104}