use std::fmt; use std::io; use command_runner::CommandRunner; use symbols::Symbol; pub struct GitCheckout<'a> { target: &'a str, source: &'a str, branch: &'a str, command_runner: &'a CommandRunner } impl<'a> GitCheckout<'a> { pub fn new(target: &'a str, source: &'a str, branch: &'a str, command_runner: &'a CommandRunner) -> GitCheckout<'a> { GitCheckout { target: target, source: source, branch: branch, command_runner: command_runner } } } impl<'a> fmt::Display for GitCheckout<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Checkout {} (branch {}) into {}", self.source, self.branch, self.target) } } use std::fs::metadata; impl<'a> GitCheckout<'a> { fn _run_in_target_repo(&self, args: &[&str]) -> Result, io::Error> { let mut new_args = vec!["-C", self.target]; new_args.extend_from_slice(args); self.command_runner.run_with_args("git", &new_args).map(|res| res.stdout) } } impl<'a> Symbol for GitCheckout<'a> { type Error = io::Error; fn target_reached(&self) -> Result { if let Err(e) = metadata(self.target) { return if e.kind() == io::ErrorKind::NotFound { Ok(false) } else { Err(e) }; } try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); let fetch_head = try!(self._run_in_target_repo(&["rev-parse", "FETCH_HEAD"])); let head = try!(self._run_in_target_repo(&["rev-parse", "HEAD"])); Ok(fetch_head == head) } fn execute(&self) -> Result<(), Self::Error> { if let Err(e) = metadata(self.target) { return if e.kind() == io::ErrorKind::NotFound { try!(self.command_runner.run_with_args("git", &["clone", "-b", self.branch, self.source, self.target])); Ok(()) } else { Err(e) }; } try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"])); Ok(()) } } #[cfg(test)] mod test { }