1use crate::manifest::Manifest;
2use crate::meme::Meme;
3use anyhow::Context;
4use std::path::PathBuf;
5use std::process::Command;
6use structopt::StructOpt;
7
8#[derive(Debug, StructOpt)]
12#[structopt(name = "build")]
13pub struct BuildCommand {
14 #[structopt(long, parse(from_os_str))]
16 manifest_path: Option<PathBuf>,
17
18 meme: Option<String>,
20
21 #[structopt(long)]
23 bin: Option<String>,
24
25 #[structopt(long)]
27 example: Option<String>,
28
29 #[structopt(long)]
31 release: bool,
32
33 #[structopt(long)]
35 subreddit: Option<String>,
36}
37
38impl BuildCommand {
39 pub fn run(&self) -> anyhow::Result<BuildOutput> {
41 let meme = if let Some(ref subreddit) = self.subreddit {
42 Meme::fetch_random_meme(subreddit)?
43 .context(format!("No jpeg meme found on subreddit {}", subreddit))?
44 } else {
45 if let Some(ref meme) = self.meme {
46 Meme::new(meme)?
47 } else {
48 if let Ok(Some(meme)) = Meme::fetch_random_meme("rustjerk") {
49 meme
50 } else {
51 if self.release {
52 Meme::new("release")?
53 } else {
54 Meme::new("debug")?
55 }
56 }
57 }
58 };
59
60 let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
61 let mut cmd = Command::new(cargo);
62 cmd.arg("build");
63
64 let (manifest, mut bin_path) = if let Some(ref path) = self.manifest_path {
65 cmd.arg("--manifest-path").arg(path);
66 (
67 Manifest::new(path)?,
68 path.parent()
69 .map(|p| p.to_path_buf())
70 .unwrap_or_else(|| PathBuf::from(".")),
71 )
72 } else {
73 (Manifest::new("./Cargo.toml")?, PathBuf::from("."))
74 };
75 bin_path.push("target");
76
77 if self.release {
78 cmd.arg("--release");
79 bin_path.push("release");
80 } else {
81 bin_path.push("debug");
82 }
83
84 let bin_name = if let Some(ref bin) = self.bin {
85 cmd.arg("--bin").arg(bin);
86 bin.clone()
87 } else if let Some(ref example) = self.example {
88 cmd.arg("--example").arg(example);
89 bin_path.push("examples");
90 example.clone()
91 } else {
92 manifest.name()?.to_string()
93 };
94 bin_path.push(&bin_name);
95
96 log::debug!("Executing: `{:?}`", cmd);
97 let child = cmd.spawn()?;
98 let output = child
99 .wait_with_output()
100 .context(format!("Error executing `{:?}`", cmd))?;
101
102 if !output.status.success() {
103 anyhow::bail!(
104 "`{:?}` failed with exit code: {:?}",
105 cmd,
106 output.status.code()
107 );
108 }
109
110 let mut meme_path = bin_path.clone();
111 meme_path.set_extension("jpeg");
112 meme.write_with_bin_to(&bin_path, &meme_path)?;
113 Ok(BuildOutput {
114 meme_path,
115 bin_path,
116 bin_name,
117 })
118 }
119}
120
121pub struct BuildOutput {
122 pub meme_path: PathBuf,
123 pub bin_path: PathBuf,
125 pub bin_name: String,
127}