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.

74 lines
2.1 KiB

7 years ago
8 years ago
8 years ago
5 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
6 years ago
5 years ago
8 years ago
5 years ago
5 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
  1. use crate::command_runner::CommandRunner;
  2. use crate::symbols::Symbol;
  3. use std::borrow::Borrow;
  4. use std::error::Error;
  5. use std::ffi::OsStr;
  6. use std::marker::PhantomData;
  7. use std::path::Path;
  8. #[derive(Debug)]
  9. pub struct Checkout<_C, C, P, S, B> {
  10. target: P,
  11. source: S,
  12. branch: B,
  13. command_runner: C,
  14. phantom: PhantomData<_C>,
  15. }
  16. impl<C, _C, P, S, B> Checkout<_C, C, P, S, B> {
  17. pub fn new(target: P, source: S, branch: B, command_runner: C) -> Self {
  18. Self {
  19. target,
  20. source,
  21. branch,
  22. command_runner,
  23. phantom: PhantomData::default(),
  24. }
  25. }
  26. }
  27. impl<C: CommandRunner, _C: Borrow<C>, P: AsRef<Path>, S, B> Checkout<C, _C, P, S, B> {
  28. fn _run_in_target_repo(&self, args: &[impl AsRef<OsStr>]) -> Result<Vec<u8>, Box<dyn Error>> {
  29. let mut new_args = vec![OsStr::new("-C"), self.target.as_ref().as_ref()];
  30. new_args.extend(args.iter().map(AsRef::as_ref));
  31. self.command_runner.borrow().get_output("git", &new_args)
  32. }
  33. }
  34. impl<C: CommandRunner, _C: Borrow<C>, P: AsRef<Path>, S: AsRef<str>, B: AsRef<str>> Symbol
  35. for Checkout<C, _C, P, S, B>
  36. {
  37. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  38. if !self.target.as_ref().exists() {
  39. return Ok(false);
  40. }
  41. self._run_in_target_repo(&["fetch", self.source.as_ref(), self.branch.as_ref()])?;
  42. // git rev-list resolves tag objects
  43. let fetch_head = self._run_in_target_repo(&["rev-list", "-1", "FETCH_HEAD"])?;
  44. let head = self._run_in_target_repo(&["rev-list", "-1", "HEAD"])?;
  45. Ok(fetch_head == head)
  46. }
  47. fn execute(&self) -> Result<(), Box<dyn Error>> {
  48. if !self.target.as_ref().exists() {
  49. return self.command_runner.borrow().run_successfully(
  50. "git",
  51. args![
  52. "clone",
  53. "--depth",
  54. "1",
  55. "-b",
  56. self.branch.as_ref(),
  57. self.source.as_ref(),
  58. self.target.as_ref(),
  59. ],
  60. );
  61. }
  62. self._run_in_target_repo(&["fetch", self.source.as_ref(), self.branch.as_ref()])?;
  63. self._run_in_target_repo(&["merge", "FETCH_HEAD"])?;
  64. Ok(())
  65. }
  66. }
  67. #[cfg(test)]
  68. mod test {}