1use std::{
4 env, fs,
5 path::Path
6};
7use crate::{
8 chainable,
9 utils::run_command
10};
11use chrono::{Local, Datelike, Timelike};
12
13mod manpage;
14
15pub use manpage::ManpageBuilder;
16
17const MONTHS: [&str; 12] = [
18 "January",
19 "February",
20 "March",
21 "April",
22 "May",
23 "June",
24 "July",
25 "August",
26 "September",
27 "October",
28 "November",
29 "December"
30];
31
32#[chainable]
34pub struct DesktopEntryFileBuilder {
35 name: String,
36 exec: String,
37 terminal: bool,
38 version: String,
39
40 #[chainable(collapse_option, use_into_impl, doc = "Add a comment to the desktop file")]
41 comment: Option<String>,
42
43 #[chainable(collapse_option, use_into_impl, doc = "Add an icon to the desktop file")]
44 icon: Option<String>,
45
46 categories: Vec<String>
47}
48
49impl DesktopEntryFileBuilder {
50 pub fn new(name: &str, exec: &str, terminal: bool, version: &str) -> Self {
52 DesktopEntryFileBuilder {
53 name: name.to_string(),
54 exec: exec.to_string(),
55 terminal,
56 version: version.to_string(),
57 comment: None,
58 icon: None,
59 categories: vec![]
60 }
61 }
62
63 pub fn category(mut self, category: &str) -> Self {
65 self.categories.push(category.to_string());
66 self
67 }
68
69 pub fn build<P: AsRef<Path>>(&self, path: P) {
71 let mut file_str = format!(
72 "[Desktop Entry]\n\
73 Version={}\n\
74 Type=Application\n\
75 Name={}\n\
76 Exec={}\n\
77 Terminal={}\n\
78 StartupNotify=false",
79 self.version, self.name, self.exec, self.terminal
80 );
81
82 if let Some(ref comment) = self.comment {
83 file_str.push_str(&format!("\nComment={comment}"));
84 }
85
86 if let Some(ref icon) = self.icon {
87 file_str.push_str(&format!("\nIcon={icon}"));
88 }
89
90 if self.categories.len() > 0 {
91 file_str.push_str("\nCategories=");
92 for category in &self.categories {
93 file_str.push_str(&format!("{category};"));
94 }
95 }
96
97 fs::remove_file(&path).unwrap_or(());
98 fs::write(&path, &file_str).unwrap();
99 }
100}
101
102pub struct AurPkgbuildBuilder {
104 name: String,
105 version: String,
106 author_name: String,
107 author_email: String,
108 desc: String,
109 source_url: String,
110 url: String,
111 license: String,
112 deps: Vec<String>,
113 make_deps: Vec<String>,
114 build_bash: String,
115 pkg_bash: String
116}
117
118impl AurPkgbuildBuilder {
119 pub fn new(
121 name: &str,
122 version: &str,
123 author_name: &str,
124 author_email: &str,
125 desc: &str,
126 source_url: &str,
127 url: &str,
128 license: &str,
129 build_bash: &str,
130 pkg_bash: &str
131 ) -> Self {
132 AurPkgbuildBuilder {
133 name: name.to_string(),
134 version: version.to_string(),
135 author_name: author_name.to_string(),
136 author_email: author_email.to_string(),
137 desc: desc.to_string(),
138 source_url: source_url.to_string(),
139 url: url.to_string(),
140 license: license.to_string(),
141 build_bash: build_bash.to_string(),
142 pkg_bash: pkg_bash.to_string(),
143 deps: vec![],
144 make_deps: vec![]
145 }
146 }
147
148 pub fn dependency(mut self, dep: &str) -> Self {
150 self.deps.push(dep.to_string());
151 self
152 }
153
154 pub fn make_dependency(mut self, dep: &str) -> Self {
156 self.make_deps.push(dep.to_string());
157 self
158 }
159
160 pub fn build<P: AsRef<Path>>(&self, dir: P) {
162 if env::set_current_dir(dir.as_ref()).is_err() { return; }
163
164 let date = Local::now().date_naive();
166 let month = MONTHS[date.month() as usize - 1];
167 let day = date.day();
168 let year = date.year();
169 let time = Local::now().time();
170 let hour = time.hour();
171 let minute = time.minute();
172 let second = time.second();
173 let time_str = format!("{hour:02}:{minute:02}:{second:02}");
174 let mut deps_str = String::new();
175 let mut make_deps_str = String::new();
176
177 for (i, dep) in self.deps.iter().enumerate() {
178 if i > 0 { deps_str.push(' '); }
179 deps_str.push_str(&format!("'{dep}'"));
180 }
181
182 for (i, dep) in self.make_deps.iter().enumerate() {
183 if i > 0 { make_deps_str.push(' '); }
184 make_deps_str.push_str(&format!("'{dep}'"));
185 }
186
187 let mut build_bash = String::new();
188 let mut pkg_bash = String::new();
189
190 for line in self.build_bash.lines() {
191 build_bash.push_str(" ");
192 build_bash.push_str(&line);
193 build_bash.push('\n');
194 }
195
196 for line in self.pkg_bash.lines() {
197 pkg_bash.push_str(" ");
198 pkg_bash.push_str(&line);
199 pkg_bash.push('\n');
200 }
201
202 let file_str = format!(
203 "# Maintainer: {} <{}>\n\
204 # Generated by cargo on {month} {day}, {year} at {time_str}\n\
205 pkgname={}\n\
206 pkgver={}\n\
207 pkgrel=1\n\
208 pkgdesc=\"{}\"\n\
209 arch=('i686' 'x86_64')\n\
210 url=\"{}\"\n\
211 license=('{}')\n\
212 depends=({deps_str})\n\
213 makedepends=({make_deps_str})\n\
214 source=(\"{}\")\n\
215 md5sums=('SKIP')\n\
216 \n\
217 build() {{\n{build_bash}}}\n\
218 \n\
219 package() {{\n{pkg_bash}}}",
220 self.author_name,
221 self.author_email,
222 self.name,
223 self.version,
224 self.desc,
225 self.url,
226 self.license,
227 self.source_url
228 );
229
230 fs::remove_file("PKGBUILD").unwrap_or(());
231 fs::remove_file(".SRCINFO").unwrap_or(());
232 fs::write("PKGBUILD", &file_str).unwrap();
233 let cmd = run_command("makepkg", false, ["--printsrcinfo"]);
234 fs::write(".SRCINFO", cmd.output).unwrap();
235 }
236}