run.rs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-FileCopyrightText: 2021 - 2022 Samuel W. Flint <swflint@flintfam.org>
  2. //
  3. // SPDX-License-Identifier: GPL-3.0-or-later
  4. use crate::lib::config::Config;
  5. use string_template::Template;
  6. use std::process::Command;
  7. use std::path::Path;
  8. use std::collections::HashMap;
  9. pub fn run(config: &Config, names: Vec<&str>) {
  10. for name in names {
  11. if config.repositories.contains_key(name) {
  12. run_repository_sync(&config, name.to_string());
  13. } else if config.groups.contains_key(name) {
  14. run_group(&config, name.to_string());
  15. } else if name == "all" {
  16. for repo_name in config.repositories.keys() {
  17. run_repository_sync(&config, repo_name.to_string());
  18. }
  19. } else {
  20. println!("\"{}\" is neither a group nor a repository.", name);
  21. }
  22. }
  23. }
  24. pub fn run_with_command(config: &Config, command: &String, names: Vec<&str>) {
  25. for name in names {
  26. if config.repositories.contains_key(name) {
  27. run_named_command(&config, name.to_string(), &command);
  28. } else if config.groups.contains_key(name) {
  29. run_group_with_command(&config, name.to_string(), &command);
  30. } else if name == "all" {
  31. for repo_name in config.repositories.keys() {
  32. run_named_command(&config, repo_name.to_string(), &command);
  33. }
  34. } else {
  35. println!("\"{}\" is neither a group nor a repository.", name);
  36. }
  37. }
  38. }
  39. fn run_command(command: String) {
  40. if !command.is_empty() {
  41. match Command::new("sh")
  42. .arg("-c")
  43. .arg(command)
  44. .spawn() {
  45. Ok(mut child) => {
  46. let mut status = child.try_wait();
  47. loop {
  48. match status {
  49. Ok(Some(_)) => break,
  50. Ok(None) => {},
  51. _ => {}
  52. }
  53. status = child.try_wait();
  54. }
  55. },
  56. _ => {}
  57. }
  58. }
  59. }
  60. fn run_command_in_directory(directory: String, command: String) {
  61. if !command.is_empty() {
  62. match Command::new("sh")
  63. .current_dir(directory)
  64. .arg("-c")
  65. .arg(command)
  66. .spawn() {
  67. Ok(mut child) => {
  68. let mut status = child.try_wait();
  69. loop {
  70. match status {
  71. Ok(Some(_)) => break,
  72. Ok(None) => {},
  73. _ => {}
  74. }
  75. status = child.try_wait();
  76. }
  77. },
  78. _ => {}
  79. }
  80. }
  81. }
  82. pub fn run_action(config: &Config, name: String) {
  83. let action = config.actions.get(&name.to_string());
  84. match action {
  85. Some(action) => {
  86. if !action.disabled {
  87. run_command(action.command.to_string());
  88. }
  89. },
  90. None => panic!("No known action named \"{}\".", name)
  91. }
  92. }
  93. pub fn run_named_command(config: &Config, repo: String, command: &String) {
  94. match config.repositories.get(&repo) {
  95. Some(repository) => {
  96. if !repository.disabled {
  97. let location = match config.is_not_default {
  98. true => {
  99. let thing = config.base_path.join(Path::new(&repository.location.to_string()));
  100. String::from(thing.to_str().unwrap())
  101. },
  102. _ => repository.location.clone()
  103. };
  104. if Path::new(&location).exists() {
  105. let mut options: HashMap<&str, &str> = HashMap::new();
  106. for (key, value) in &repository.options {
  107. options.insert(key, value);
  108. }
  109. options.insert("location", &location);
  110. match config.repo_types.get(&repository.repo_type) {
  111. Some(repo_type) => {
  112. match repo_type.commands.get(command) {
  113. Some(command_string) => {
  114. println!("\n\nRepository {} ({}):", repo, location);
  115. run_command_in_directory(location.to_string(),
  116. Template::new(&command_string).render(&options));
  117. },
  118. None => {}
  119. }
  120. },
  121. None => panic!("No repository type named \"{}\".", repository.repo_type)
  122. }
  123. }
  124. }
  125. }
  126. None => panic!("No known repository named \"{}\".", repo)
  127. }
  128. }
  129. pub fn run_repository_sync(config: &Config, name: String) {
  130. let repository = config.repositories.get(&name.to_string());
  131. match repository {
  132. Some(repository) => {
  133. if !repository.disabled {
  134. let location = match config.is_not_default {
  135. true => {
  136. let thing = config.base_path.join(Path::new(&repository.location.to_string()));
  137. String::from(thing.to_str().unwrap())
  138. },
  139. _ => repository.location.clone()
  140. };
  141. if !Path::new(&location).exists() {
  142. if repository.auto_create {
  143. run_repository_creation(config, name);
  144. }
  145. } else {
  146. let mut options: HashMap<&str, &str> = HashMap::new();
  147. for (key, value) in &repository.options {
  148. options.insert(key, value);
  149. }
  150. options.insert("location", &location);
  151. let repo_type = config.repo_types.get(&repository.repo_type);
  152. match repo_type {
  153. Some(repo_type) => {
  154. println!("\n\nRepository {} ({}):", name, location);
  155. run_command_in_directory(location.to_string(),
  156. Template::new(&repo_type.pre_inward).render(&options));
  157. run_command_in_directory(location.to_string(),
  158. Template::new(&repo_type.inward).render(&options));
  159. run_command_in_directory(location.to_string(),
  160. Template::new(&repo_type.post_inward).render(&options));
  161. run_command_in_directory(location.to_string(),
  162. Template::new(&repo_type.outward).render(&options));
  163. run_command_in_directory(location.to_string(),
  164. Template::new(&repo_type.post_outward).render(&options));
  165. },
  166. None => panic!("No known repository type named \"{}\".", &repository.repo_type)
  167. }
  168. }
  169. }
  170. },
  171. None => panic!("No known repository named \"{}\".", name)
  172. }
  173. }
  174. pub fn run_repository_creation(config: &Config, name: String) {
  175. let repository = config.repositories.get(&name.to_string());
  176. match repository {
  177. Some(repository) => {
  178. let repository_type_name = &repository.repo_type;
  179. let repository_type = config.repo_types.get(repository_type_name);
  180. match repository_type {
  181. Some(repository_type) => {
  182. if !repository.disabled {
  183. let mut options: HashMap<&str, &str> = HashMap::new();
  184. for (key, value) in &repository.options {
  185. options.insert(key, value);
  186. }
  187. options.insert("location", &repository.location);
  188. run_command(Template::new(&repository_type.create).render(&options));
  189. }
  190. },
  191. None => panic!("No known repository type named \"{}\".", repository_type_name)
  192. }
  193. },
  194. None => panic!("No known repository named \"{}\".", name)
  195. }
  196. }
  197. pub fn run_group(config: &Config, name: String) {
  198. let group = config.groups.get(&name.to_string());
  199. match group {
  200. Some(group) => {
  201. for member in &group.members {
  202. if config.repositories.contains_key(member) {
  203. run_repository_sync(&config, member.to_string());
  204. } else if config.groups.contains_key(member) {
  205. run_group(&config, member.to_string());
  206. } else {
  207. println!("\"{}\" is neither a group nor a repository.", member);
  208. }
  209. }
  210. for action in &group.actions_after {
  211. run_action(&config, action.to_string());
  212. }
  213. },
  214. None => panic!("No known group named \"{}\".", name)
  215. }
  216. }
  217. pub fn run_group_with_command(config: &Config, name: String, command: &String) {
  218. let group = config.groups.get(&name.to_string());
  219. match group {
  220. Some(group) => {
  221. for member in &group.members {
  222. if config.repositories.contains_key(member) {
  223. run_named_command(&config, member.to_string(), &command);
  224. } else if config.groups.contains_key(member) {
  225. run_group_with_command(&config, member.to_string(), &command);
  226. } else {
  227. println!("\"{}\" is neither a group nor a repository.", member);
  228. }
  229. }
  230. for action in &group.actions_after {
  231. run_action(&config, action.to_string());
  232. }
  233. },
  234. None => panic!("No known group named \"{}\".", name)
  235. }
  236. }