A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.6 KiB

7 years ago
6 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
5 years ago
7 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
7 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
7 years ago
5 years ago
6 years ago
7 years ago
  1. use regex::Regex;
  2. use std::error::Error;
  3. use std::fmt;
  4. use std::fs::File as FsFile;
  5. use std::io;
  6. use std::io::{BufRead, BufReader};
  7. use std::ops::Deref;
  8. use std::path::{Path, PathBuf};
  9. use command_runner::CommandRunner;
  10. use resources::Resource;
  11. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  12. pub struct WordpressPlugin<'a, C, R>
  13. where
  14. C: Deref<Target = str>,
  15. R: 'a + CommandRunner,
  16. {
  17. base: C,
  18. name: C,
  19. command_runner: &'a R,
  20. }
  21. impl<'a, C, R> WordpressPlugin<'a, C, R>
  22. where
  23. C: Deref<Target = str>,
  24. R: CommandRunner,
  25. {
  26. pub fn new(base: C, name: C, command_runner: &'a R) -> Self {
  27. WordpressPlugin {
  28. base,
  29. name,
  30. command_runner,
  31. }
  32. }
  33. fn get_path(&self) -> PathBuf {
  34. Path::new(&*self.base)
  35. .join("wp-content/plugins")
  36. .join(&*self.name)
  37. }
  38. }
  39. impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R>
  40. where
  41. C: Deref<Target = str>,
  42. R: CommandRunner,
  43. {
  44. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  45. if !self.get_path().exists() {
  46. return Ok(false);
  47. }
  48. let path = self.get_path().join(self.name.to_string() + ".php");
  49. let mut version = String::new();
  50. let mut plugin_uri = String::new();
  51. match FsFile::open(path) {
  52. Err(e) => {
  53. // Check if file exists
  54. return if e.kind() == io::ErrorKind::NotFound {
  55. Ok(false)
  56. } else {
  57. Err(Box::new(e))
  58. };
  59. }
  60. Ok(file) => {
  61. let reader = BufReader::new(file);
  62. let regex = Regex::new("(?m)^(Plugin URI|Version): (.+)$")?;
  63. for content in reader.lines() {
  64. for matches in regex.captures_iter(&(content?)) {
  65. if &matches[1] == "Plugin URI" {
  66. plugin_uri = matches[2].to_string();
  67. } else {
  68. version = matches[2].to_string();
  69. }
  70. }
  71. }
  72. }
  73. }
  74. let upstream = self.command_runner.get_output(
  75. "curl",
  76. &[
  77. "--form",
  78. &format!(
  79. r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###,
  80. &*self.name, version, plugin_uri
  81. ),
  82. "https://api.wordpress.org/plugins/update-check/1.1/",
  83. ],
  84. )?;
  85. Ok(String::from_utf8(upstream)?.contains(r###""plugins":[]"###))
  86. }
  87. fn execute(&self) -> Result<(), Box<dyn Error>> {
  88. let source = format!("https://downloads.wordpress.org/plugin/{}.zip", &*self.name);
  89. let zip = format!("/tmp/{}.zip", &*self.name);
  90. self
  91. .command_runner
  92. .run_successfully("curl", &[source.as_ref() as &str, "-o", zip.as_ref()])?;
  93. self
  94. .command_runner
  95. .run_successfully("rm", &["-rf", &self.get_path().to_string_lossy()])?;
  96. self.command_runner.run_successfully(
  97. "unzip",
  98. &[
  99. zip.as_ref(),
  100. "-d".as_ref(),
  101. Path::new(&*self.base)
  102. .join("wp-content/plugins")
  103. .as_os_str(),
  104. ],
  105. )
  106. }
  107. fn get_prerequisites(&self) -> Vec<Resource> {
  108. match self.get_path().parent() {
  109. Some(p) => vec![Resource::new("dir", p.to_string_lossy())],
  110. None => vec![],
  111. }
  112. }
  113. fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b> {
  114. Box::new(SymbolAction::new(runner, self))
  115. }
  116. fn into_action<'b>(self: Box<Self>, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b>
  117. where
  118. Self: 'b,
  119. {
  120. Box::new(OwnedSymbolAction::new(runner, *self))
  121. }
  122. }
  123. impl<'a, C, R> fmt::Display for WordpressPlugin<'a, C, R>
  124. where
  125. C: Deref<Target = str>,
  126. R: CommandRunner,
  127. {
  128. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
  129. write!(f, "WordpressPlugin {}", &*self.name)
  130. }
  131. }