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.

84 lines
2.3 KiB

8 years ago
7 years ago
8 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
8 years ago
8 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::Symbol;
  8. pub struct GitCheckout<'a> {
  9. target: &'a str,
  10. source: &'a str,
  11. branch: &'a str,
  12. command_runner: &'a CommandRunner
  13. }
  14. impl<'a> GitCheckout<'a> {
  15. pub fn new(target: &'a str, source: &'a str, branch: &'a str, command_runner: &'a CommandRunner) -> GitCheckout<'a> {
  16. GitCheckout {
  17. target: target,
  18. source: source,
  19. branch: branch,
  20. command_runner: command_runner
  21. }
  22. }
  23. }
  24. impl<'a> fmt::Display for GitCheckout<'a> {
  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> GitCheckout<'a> {
  31. fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, io::Error> {
  32. let mut new_args = vec!["-C", self.target];
  33. new_args.extend_from_slice(args);
  34. self.command_runner.run_with_args("git", &new_args).map(|res| res.stdout)
  35. }
  36. }
  37. impl<'a> Symbol for GitCheckout<'a> {
  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 let Err(e) = metadata(self.target) {
  53. return if e.kind() == io::ErrorKind::NotFound {
  54. try!(self.command_runner.run_with_args("git", &["clone", "--depth", "1", "-b", self.branch, self.source, self.target]));
  55. Ok(())
  56. } else {
  57. Err(Box::new(e))
  58. };
  59. }
  60. try!(self._run_in_target_repo(&["fetch", self.source, self.branch]));
  61. try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"]));
  62. Ok(())
  63. }
  64. fn get_prerequisites(&self) -> Vec<Resource> {
  65. vec![ Resource::new("dir", Path::new(self.target).parent().unwrap().to_string_lossy()) ]
  66. }
  67. fn provides(&self) -> Option<Vec<Resource>> {
  68. Some(vec![ Resource::new("dir", self.target.to_string()) ])
  69. }
  70. }
  71. #[cfg(test)]
  72. mod test {
  73. }