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.

87 lines
2.6 KiB

8 years ago
7 years ago
8 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
8 years ago
7 years ago
8 years ago
8 years ago
8 years ago
7 years ago
8 years ago
7 years ago
7 years ago
8 years ago
  1. use std::error::Error;
  2. use std::fmt;
  3. use std::io;
  4. use std::path::Path;
  5. use command_runner::CommandRunner;
  6. use resources::Resource;
  7. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  8. pub struct GitCheckout<'a, C: 'a + CommandRunner> {
  9. target: &'a str,
  10. source: &'a str,
  11. branch: &'a str,
  12. command_runner: &'a C
  13. }
  14. impl<'a, C: CommandRunner> GitCheckout<'a, C> {
  15. pub fn new(target: &'a str, source: &'a str, branch: &'a str, command_runner: &'a C) -> Self {
  16. GitCheckout {
  17. target: target,
  18. source: source,
  19. branch: branch,
  20. command_runner: command_runner
  21. }
  22. }
  23. }
  24. impl<'a, C: CommandRunner> fmt::Display for GitCheckout<'a, C> {
  25. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  26. write!(f, "Checkout {} (branch {}) into {}", self.source, self.branch, self.target)
  27. }
  28. }
  29. use std::fs::metadata;
  30. impl<'a, C: CommandRunner> GitCheckout<'a, C> {
  31. fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, Box<Error>> {
  32. let mut new_args = vec!["-C", self.target];
  33. new_args.extend_from_slice(args);
  34. self.command_runner.get_output("git", &new_args)
  35. }
  36. }
  37. impl<'a, C: CommandRunner> Symbol for GitCheckout<'a, C> {
  38. fn target_reached(&self) -> Result<bool, Box<Error>> {
  39. if let Err(e) = metadata(self.target) {
  40. return if e.kind() == io::ErrorKind::NotFound {
  41. Ok(false)
  42. } else {
  43. Err(Box::new(e))
  44. };
  45. }
  46. try!(self._run_in_target_repo(&["fetch", self.source, self.branch]));
  47. let fetch_head = try!(self._run_in_target_repo(&["rev-parse", "FETCH_HEAD"]));
  48. let head = try!(self._run_in_target_repo(&["rev-parse", "HEAD"]));
  49. Ok(fetch_head == head)
  50. }
  51. fn execute(&self) -> Result<(), Box<Error>> {
  52. if !Path::new(self.target).exists() {
  53. return self.command_runner.run_successfully("git", &["clone", "--depth", "1", "-b", self.branch, self.source, self.target]);
  54. }
  55. try!(self._run_in_target_repo(&["fetch", self.source, self.branch]));
  56. try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"]));
  57. Ok(())
  58. }
  59. fn get_prerequisites(&self) -> Vec<Resource> {
  60. vec![ Resource::new("dir", Path::new(self.target).parent().unwrap().to_string_lossy()) ]
  61. }
  62. fn provides(&self) -> Option<Vec<Resource>> {
  63. Some(vec![ Resource::new("dir", self.target.to_string()) ])
  64. }
  65. fn as_action<'b>(&'b self, runner: &'b SymbolRunner) -> Box<Action + 'b> {
  66. Box::new(SymbolAction::new(runner, self))
  67. }
  68. fn into_action<'b>(self: Box<Self>, runner: &'b SymbolRunner) -> Box<Action + 'b> where Self: 'b {
  69. Box::new(OwnedSymbolAction::new(runner, *self))
  70. }
  71. }
  72. #[cfg(test)]
  73. mod test {
  74. }