artifact_app/cmd/
mod.rs

1/* Copyright (c) 2017 Garrett Berg, vitiral@gmail.com
2 *
3 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 * http://opensource.org/licenses/MIT>, at your option. This file may not be
6 * copied, modified, or distributed except according to those terms.
7 */
8//! cmdline: utilities and methods to display information on the
9//! command line
10//!
11//! this module contains trait implementations and other sugar
12//! to help with displaying artifact artifacts on the cmd line
13//! as well as functions which map easily to cmdline methods
14//! that the user may want to execute
15
16use dev_prefix::*;
17use types::*;
18use logging;
19use user;
20use utils;
21use security;
22
23use clap::{ArgMatches, ErrorKind as ClEk};
24use ansi_term::Colour::Green;
25
26mod export;
27mod types;
28mod matches;
29mod ls;
30pub mod check;
31mod display;
32mod fmt;
33mod init;
34mod tutorial;
35mod update;
36#[cfg(feature = "beta")]
37mod plugin;
38
39mod server;
40
41#[cfg(test)]
42mod tests;
43
44pub fn get_loglevel(matches: &ArgMatches) -> (u8, bool) {
45    let verbosity = match matches.occurrences_of("verbose") {
46        v @ 0...3 => v,
47        _ => {
48            // v > 3
49            eprintln!("WARN: verbosity cannot be higher than 3, defaulting to 3");
50            3
51        }
52    } as u8;
53    let quiet = matches.is_present("quiet");
54    (verbosity, quiet)
55}
56
57#[cfg(feature = "beta")]
58/// run beta commands here
59fn run_beta<W>(_project: Option<&Project>, matches: &ArgMatches, w: &mut W) -> Result<u8>
60where
61    W: io::Write,
62{
63    if let Some(mat) = matches.subcommand_matches("plugin") {
64        info!("Calling plugin command");
65        let c = plugin::get_cmd(mat)?;
66        plugin::run_cmd(&c, w)
67    } else {
68        Err(ErrorKind::NothingDone.into())
69    }
70}
71
72#[cfg(not(feature = "beta"))]
73/// run beta commands in the `[#cfg(feature = "beta")]` function
74fn run_beta<W>(_: Option<&Project>, _: &ArgMatches, _: &mut W) -> Result<u8>
75where
76    W: io::Write,
77{
78    Err(ErrorKind::NothingDone.into())
79}
80
81pub fn cmd<W, I, T>(w: &mut W, args: I) -> Result<u8>
82where
83    I: IntoIterator<Item = T>,
84    T: Into<OsString> + clone::Clone,
85    W: io::Write,
86{
87    let matches = match matches::get_matches(args) {
88        Ok(m) => m,
89        Err(e) => match e.kind {
90            ClEk::HelpDisplayed | ClEk::VersionDisplayed => {
91                eprint!("{}", e);
92                return Ok(0);
93            }
94            _ => return Err(ErrorKind::CmdError(e.to_string()).into()),
95        },
96    };
97
98    // initialze the logger
99    let (v, q) = get_loglevel(&matches);
100    logging::init_logger(q, v, true).unwrap();
101
102    // if we are updating, just do that and exit
103    if let Some(up) = matches.subcommand_matches("update") {
104        info!("Calling the update command");
105        let cmd = update::get_cmd(up);
106        return Ok(update::run_cmd(&cmd).expect("update failed"));
107    }
108
109    let cwd = env::current_dir().unwrap();
110    let work_tree = match matches.value_of("work-tree") {
111        Some(w) => PathBuf::from(w),
112        None => cwd.to_path_buf(),
113    };
114    if !work_tree.is_dir() {
115        let msg = format!(
116            "ERROR: work-tree {} is not a directory",
117            work_tree.display()
118        );
119        return Err(ErrorKind::CmdError(msg).into());
120    }
121
122    // If init is selected, do that
123    if matches.subcommand_matches("init").is_some() {
124        info!("Calling the init command");
125        init::run_cmd(&work_tree)?;
126        return Ok(0);
127    }
128
129    // If tutorial is selected, do that
130    if let Some(t) = matches.subcommand_matches("tutorial") {
131        info!("Calling the tutorial command");
132        let c = tutorial::get_cmd(t)?;
133        tutorial::run_cmd(&work_tree, c).unwrap();
134        return Ok(0);
135    }
136
137    // If plugin is selected, run it.
138    // NB: plugin is a BETA command
139    if matches.subcommand_matches("plugin").is_some() {
140        return run_beta(None, &matches, w);
141    }
142
143    // load the artifacts
144    let repo = match utils::find_repo(&work_tree) {
145        Ok(r) => r,
146        Err(_) => {
147            let msg = "Could not find .art folder. Try running `art init`";
148            return Err(ErrorKind::CmdError(msg.to_string()).into());
149        }
150    };
151    debug!("Using repo dir {:?}", repo);
152
153    let project = user::load_repo(&repo)?;
154
155    // SPC-security: do security checks on the project
156    security::validate(&repo, &project)?;
157
158    debug!("settings={:?}", project.settings);
159
160    if let Some(ls) = matches.subcommand_matches("ls") {
161        info!("Calling the ls command");
162        let cmd = ls::get_cmd(ls).unwrap();
163        ls::run_cmd(w, &work_tree, &cmd, &project)
164    } else if matches.subcommand_matches("check").is_some() {
165        info!("Calling the check command");
166        let cmd = check::Cmd {
167            color: types::COLOR_IF_POSSIBLE,
168        };
169        check::run_cmd(w, &work_tree, &project, &cmd)
170    } else if let Some(mat) = matches.subcommand_matches("fmt") {
171        info!("Calling the fmt command");
172        let c = fmt::get_cmd(mat)?;
173        fmt::run_cmd(w, &repo, &project, &c)
174    } else if let Some(mat) = matches.subcommand_matches("export") {
175        info!("Calling the export command");
176        let c = export::get_cmd(mat)?;
177        export::run_cmd(&cwd, &project, &c)
178    } else if let Some(mat) = matches.subcommand_matches("serve") {
179        let addr = server::get_cmd(mat);
180        server::run_cmd(project.clone(), &addr);
181        Ok(0)
182    } else if match run_beta(Some(&project), &matches, w) {
183        Ok(r) => return Ok(r),
184        Err(err) => match *err.kind() {
185            ErrorKind::NothingDone => false,
186            _ => return Err(err),
187        },
188    } {
189        unreachable!();
190    } else {
191        write!(
192            w,
193            "{} {}: use -h to show help",
194            Green.bold().paint("artifact"),
195            Green.paint(VERSION)
196        ).unwrap();
197        return Ok(0);
198    }
199}