-
Notifications
You must be signed in to change notification settings - Fork 6
/
run.rs
162 lines (134 loc) · 5.67 KB
/
run.rs
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use crate::command::CommandResult;
use crate::{command::Command, game_metadata};
use clap::ArgMatches;
use derive_more::Display;
use derive_more::Error;
use log::*;
use serde::Serialize;
use smaug_lib::dragonruby;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::process;
use std::fs::{File, create_dir};
use std::io::prelude::*;
use dunce;
#[derive(Debug)]
pub struct Run;
#[derive(Debug, Serialize, Display)]
#[display(fmt = "Ran project {} as process {}", "project_name", "pid")]
pub struct RunResult {
project_name: String,
pid: u32,
}
#[derive(Debug, Display, Error, Serialize)]
pub enum Error {
#[display(
fmt = "Could not find the configured version of DragonRuby. Install it with `smaug dragonruby install`"
)]
ConfiguredDragonRubyNotFound,
#[display(fmt = "Couldn't load Smaug configuration.")]
Config { path: PathBuf },
#[display(
fmt = "{} crashed look at the logs for more information",
"project_name"
)]
Run { project_name: String },
}
impl Command for Run {
fn run(&self, matches: &ArgMatches) -> CommandResult {
trace!("Run Command");
let dragonruby_options: Vec<&str> = matches
.values_of("DRAGONRUBY_ARGS")
.unwrap_or_default()
.collect();
let httpd = matches.is_present("http");
let current_directory = env::current_dir().unwrap();
let directory: &str = matches
.value_of("path")
.unwrap_or_else(|| current_directory.to_str().unwrap());
debug!("Directory: {}", directory);
let path = Path::new(directory);
let path = dunce::canonicalize(&path).expect("Could not find path");
debug!("path: {:?}", path);
let config_path = path.join("Smaug.toml");
let config = match smaug_lib::config::load(&config_path) {
Ok(config) => config,
Err(..) => return Err(Box::new(Error::Config { path: config_path })),
};
debug!("Smaug config: {:?}", config);
let metadata_file = path.join("metadata").join("game_metadata.txt");
debug!("{:?}", metadata_file);
let metadata_file =
dunce::canonicalize(&metadata_file).expect("Could not create canonical path");
trace!("Writing game metadata to {}.", metadata_file.display());
let metadata = game_metadata::from_config(&config);
metadata
.write(&metadata_file)
.expect("Could not write game metadata.");
let dragonruby = dragonruby::configured_version(&config);
match dragonruby {
None => Err(Box::new(Error::ConfiguredDragonRubyNotFound)),
Some(dragonruby) => {
let bin_dir = dragonruby.install_dir();
let log_dir = bin_dir.join("logs");
let exception_dir = bin_dir.join("exceptions");
rm_rf::ensure_removed(&log_dir).expect("couldn't remove logs");
rm_rf::ensure_removed(&exception_dir).expect("couldn't remove exceptions");
debug!("DragonRuby Directory: {}", bin_dir.to_str().unwrap());
let mut bin = bin_dir.join(dragonruby::dragonruby_bin_name());
if httpd {
bin = bin_dir.join(dragonruby::dragonruby_httpd_name());
}
trace!(
"Spawning Process {} {} {}",
bin.to_str().unwrap(),
path.to_str().unwrap(),
dragonruby_options.join(" ")
);
let quiet = matches.is_present("json") || matches.is_present("quiet");
let stdout = if quiet {
process::Stdio::null()
} else {
process::Stdio::inherit()
};
let mut child = process::Command::new(bin)
.arg(path.clone())
.args(dragonruby_options)
.stdout(stdout)
.spawn()
.unwrap();
let local_log_dir = path.join("logs");
if !local_log_dir.is_dir() {
create_dir(&local_log_dir)
.expect("couldn't create local logs");
}
let mut file = File::create(&local_log_dir.join("pid.lock")).unwrap();
file.write_fmt(format_args!("{}", child.id())).unwrap();
let status = child.wait().unwrap();
rm_rf::ensure_removed(&local_log_dir).expect("Couldn't remove local logs");
let local_exception_dir = path.join("exceptions");
rm_rf::ensure_removed(&local_exception_dir)
.expect("Couldn't remove local exceptions");
if log_dir.is_dir() {
smaug_lib::util::dir::copy_directory(&log_dir, local_log_dir)
.expect("couldn't copy logs");
}
if exception_dir.is_dir() {
smaug_lib::util::dir::copy_directory(&exception_dir, local_exception_dir)
.expect("couldn't copy exceptions");
}
if status.success() {
Ok(Box::new(RunResult {
project_name: config.project.unwrap().name,
pid: child.id(),
}))
} else {
Err(Box::new(Error::Run {
project_name: config.project.unwrap().name,
}))
}
}
}
}
}