Merge pull request #6 from fisherdarling/update-to-2018

Updated to 2018 edition. Refactored some sections.
pull/7/head
Sebastian Geisler 5 years ago committed by GitHub
commit c83b18b6f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,12 +8,12 @@ version = "0.1.2"
authors = ["Sebastian Geisler <sgeisler@wh2.tu-dresden.de>"] authors = ["Sebastian Geisler <sgeisler@wh2.tu-dresden.de>"]
license = "MIT" license = "MIT"
repository = "https://github.com/sgeisler/cargo-remote" repository = "https://github.com/sgeisler/cargo-remote"
edition = "2018"
[dependencies] [dependencies]
structopt = "0.1.6" structopt = "0.2.18"
structopt-derive = "0.1.6" cargo_metadata = "0.8.0"
cargo_metadata = "0.4.1"
log = "0.4.1" log = "0.4.1"
simple_logger = "0.4.0" simple_logger = "1.3.0"
toml = "0.4.5" toml = "0.5.1"
xdg = "2.1.0" xdg = "2.1.0"

@ -1,31 +1,13 @@
extern crate structopt;
#[macro_use]
extern crate structopt_derive;
extern crate cargo_metadata;
#[macro_use] extern crate log;
extern crate simple_logger;
extern crate toml;
extern crate xdg;
use std::process::{exit, Command, Stdio};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs::File; use std::process::{exit, Command, Stdio};
use std::io::Read;
use std::borrow::Borrow;
use structopt::StructOpt; use structopt::StructOpt;
use toml::Value; use toml::Value;
use log::{error, info, warn};
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt( #[structopt(name = "cargo-remote", bin_name = "cargo")]
name = "cargo-remote",
bin_name = "cargo",
)]
enum Opts { enum Opts {
#[structopt(name = "remote")] #[structopt(name = "remote")]
Remote { Remote {
@ -42,9 +24,10 @@ enum Opts {
#[structopt( #[structopt(
long = "manifest-path", long = "manifest-path",
help = "Path to the manifest to execute", help = "Path to the manifest to execute",
default_value = "Cargo.toml",
parse(from_os_str) parse(from_os_str)
)] )]
manifest_path: Option<PathBuf>, manifest_path: PathBuf,
#[structopt( #[structopt(
short = "h", short = "h",
@ -61,98 +44,104 @@ enum Opts {
name = "remote options" name = "remote options"
)] )]
options: Vec<String>, options: Vec<String>,
} },
} }
/// Tries to parse the file [`config_path`]. Logs warnings and returns [`None`] if errors occur /// Tries to parse the file [`config_path`]. Logs warnings and returns [`None`] if errors occur
/// during reading or parsing, [`Some(Value)`] otherwise. /// during reading or parsing, [`Some(Value)`] otherwise.
fn config_from_file(config_path: &Path) -> Option<Value> { fn config_from_file(config_path: &Path) -> Option<Value> {
File::open(config_path).ok().and_then(|mut file| { let config_file = std::fs::read_to_string(config_path)
let mut config_file_string = "".to_owned(); .map_err(|e| {
file.read_to_string(&mut config_file_string).or_else(|e| { warn!(
warn!("Can't read config file '{}' (error: {})", config_path.to_string_lossy(), e); "Can't parse config file '{}' (error: {})",
Err(e) config_path.to_string_lossy(),
}).ok()?; e
config_file_string.parse::<Value>().or_else(|e| { );
warn!("Can't parse config file '{}' (error: {})", config_path.to_string_lossy(), e); })
Err(e) .ok()?;
}).ok()
}) let value = config_file
.parse::<Value>()
.map_err(|e| {
warn!(
"Can't parse config file '{}' (error: {})",
config_path.to_string_lossy(),
e
);
})
.ok()?;
Some(value)
} }
fn main() { fn main() {
simple_logger::init().unwrap(); simple_logger::init().unwrap();
let Opts::Remote{ let Opts::Remote {
remote, remote,
copy_back, copy_back,
manifest_path, manifest_path,
hidden, hidden,
command, command,
options options,
} = Opts::from_args(); } = Opts::from_args();
let manifest_path = manifest_path.as_ref().map(PathBuf::borrow); let mut metadata_cmd = cargo_metadata::MetadataCommand::new();
let project_metadata = cargo_metadata::metadata(manifest_path) metadata_cmd.manifest_path(manifest_path).no_deps();
.unwrap_or_else(|e| {
error!("Could not read cargo metadata: {}", e); let project_metadata = metadata_cmd.exec().unwrap();
exit(-1);
});
// for now, assume that there is only one project and find it's root directory // for now, assume that there is only one project and find it's root directory
let (project_dir, project_name) = project_metadata.packages.first().map_or_else(|| { let (project_dir, project_name) = project_metadata.packages.first().map_or_else(
error!("No project found."); || {
exit(-2); error!("No project found.");
}, |project| { exit(-2);
( },
Path::new(&project.manifest_path) |project| (&project_metadata.workspace_root, &project.name),
.parent() );
.expect("Cargo.toml seems to have no parent directory?"),
&project.name
)
});
let configs = vec![ let configs = vec![
config_from_file(&project_dir.join(".cargo-remote.toml")), config_from_file(&project_dir.join(".cargo-remote.toml")),
xdg::BaseDirectories::with_prefix("cargo-remote") xdg::BaseDirectories::with_prefix("cargo-remote")
.ok() .ok()
.and_then(|base| base.find_config_file("cargo-remote.toml")) .and_then(|base| base.find_config_file("cargo-remote.toml"))
.and_then(|p: PathBuf| config_from_file(&p) .and_then(|p: PathBuf| config_from_file(&p)),
),
]; ];
// TODO: move Opts::Remote fields into own type and implement complete_from_config(&mut self, config: &Value) // TODO: move Opts::Remote fields into own type and implement complete_from_config(&mut self, config: &Value)
let build_server = remote.or_else(|| { let build_server = remote
configs.into_iter() .or_else(|| {
.flat_map(|config| { configs
config.and_then(|c| { .into_iter()
c["remote"].as_str().map(str::to_owned) .flat_map(|config| config.and_then(|c| c["remote"].as_str().map(String::from)))
}) .next()
}) })
.next() .unwrap_or_else(|| {
}).unwrap_or_else(|| { error!("No remote build server was defined (use config file or --remote flag)");
error!("No remote build server was defined (use config file or --remote flag)"); exit(-3);
exit(-3); });
});
let build_path = format!("~/remote-builds/{}/", project_name);
info!("Transferring sources to build server."); info!("Transferring sources to build server.");
// transfer project to build server // transfer project to build server
let mut rsync_to = Command::new("rsync"); let mut rsync_to = Command::new("rsync");
rsync_to.arg("-a".to_owned()) rsync_to
.arg("-a".to_owned())
.arg("--delete") .arg("--delete")
.arg("--info=progress2") .arg("--info=progress2")
.arg("--exclude") .arg("--exclude")
.arg("target"); .arg("target");
if !hidden { if !hidden {
rsync_to.arg("--exclude") rsync_to.arg("--exclude").arg(".*");
.arg(".*");
} }
rsync_to.arg("--rsync-path") rsync_to
.arg("--rsync-path")
.arg("mkdir -p remote-builds && rsync") .arg("mkdir -p remote-builds && rsync")
.arg(format!("{}/", project_dir.to_string_lossy())) .arg(format!("{}/", project_dir.to_string_lossy()))
.arg(format!("{}:~/remote-builds/{}/", build_server, project_name)) .arg(format!("{}:{}", build_server, build_path))
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
@ -163,17 +152,15 @@ fn main() {
}); });
let build_command = format!( let build_command = format!(
"cd ~/remote-builds/{}/; $HOME/.cargo/bin/cargo {} {}", "cd {}; $HOME/.cargo/bin/cargo {} {}",
project_name, build_path,
command, command,
options.iter().fold( options.join(" ")
String::new(),
|acc, x| format!("{} {}", acc, x)
)
); );
info!("Starting build process."); info!("Starting build process.");
Command::new("ssh") Command::new("ssh")
.arg("-t")
.arg(&build_server) .arg(&build_server)
.arg(build_command) .arg(build_command)
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
@ -192,14 +179,17 @@ fn main() {
.arg("--delete") .arg("--delete")
.arg("--compress") .arg("--compress")
.arg("--info=progress2") .arg("--info=progress2")
.arg(format!("{}:~/remote-builds/{}/target/", build_server, project_name)) .arg(format!("{}:{}/target/", build_server, build_path))
.arg(format!("{}/target/", project_dir.to_string_lossy())) .arg(format!("{}/target/", project_dir.to_string_lossy()))
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.output() .output()
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!("Failed to transfer target back to local machine (error: {})", e); error!(
"Failed to transfer target back to local machine (error: {})",
e
);
exit(-6); exit(-6);
}); });
} }

Loading…
Cancel
Save