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.

113 lines
3.1 KiB

8 years ago
8 years ago
7 years ago
8 years ago
8 years ago
6 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
7 years ago
8 years ago
5 years ago
5 years ago
6 years ago
8 years ago
8 years ago
5 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
7 years ago
5 years ago
5 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
8 years ago
5 years ago
  1. use std::error::Error;
  2. use std::ffi::OsStr;
  3. use std::fmt;
  4. use std::fs::metadata;
  5. use std::io;
  6. use std::path::Path;
  7. use crate::command_runner::CommandRunner;
  8. use crate::resources::Resource;
  9. use crate::symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  10. pub struct GitCheckout<'a, C: CommandRunner, T: AsRef<Path>> {
  11. target: T,
  12. source: &'a str,
  13. branch: &'a str,
  14. command_runner: &'a C,
  15. }
  16. impl<'a, C: CommandRunner, T: AsRef<Path>> GitCheckout<'a, C, T> {
  17. pub fn new(target: T, source: &'a str, branch: &'a str, command_runner: &'a C) -> Self {
  18. GitCheckout {
  19. target,
  20. source,
  21. branch,
  22. command_runner,
  23. }
  24. }
  25. }
  26. impl<C: CommandRunner, T: AsRef<Path>> fmt::Display for GitCheckout<'_, C, T> {
  27. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  28. write!(
  29. f,
  30. "Checkout {} (branch {}) into {}",
  31. self.source,
  32. self.branch,
  33. self.target.as_ref().display()
  34. )
  35. }
  36. }
  37. impl<C: CommandRunner, T: AsRef<Path>> GitCheckout<'_, C, T> {
  38. fn _run_in_target_repo<S: AsRef<OsStr>>(&self, args: &[S]) -> Result<Vec<u8>, Box<dyn Error>> {
  39. let mut new_args = vec![OsStr::new("-C"), self.target.as_ref().as_ref()];
  40. new_args.extend(args.iter().map(AsRef::as_ref));
  41. self.command_runner.get_output("git", &new_args)
  42. }
  43. }
  44. impl<C: CommandRunner, T: AsRef<Path>> Symbol for GitCheckout<'_, C, T> {
  45. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  46. if let Err(e) = metadata(self.target.as_ref()) {
  47. return if e.kind() == io::ErrorKind::NotFound {
  48. Ok(false)
  49. } else {
  50. Err(Box::new(e))
  51. };
  52. }
  53. self._run_in_target_repo(&["fetch", self.source, self.branch])?;
  54. // git rev-list resolves tag objects
  55. let fetch_head = self._run_in_target_repo(&["rev-list", "-1", "FETCH_HEAD"])?;
  56. let head = self._run_in_target_repo(&["rev-list", "-1", "HEAD"])?;
  57. Ok(fetch_head == head)
  58. }
  59. fn execute(&self) -> Result<(), Box<dyn Error>> {
  60. if !self.target.as_ref().exists() {
  61. return self.command_runner.run_successfully(
  62. "git",
  63. &[
  64. OsStr::new("clone"),
  65. "--depth".as_ref(),
  66. "1".as_ref(),
  67. "-b".as_ref(),
  68. self.branch.as_ref(),
  69. self.source.as_ref(),
  70. self.target.as_ref().as_ref(),
  71. ],
  72. );
  73. }
  74. self._run_in_target_repo(&["fetch", self.source, self.branch])?;
  75. self._run_in_target_repo(&["merge", "FETCH_HEAD"])?;
  76. Ok(())
  77. }
  78. fn get_prerequisites(&self) -> Vec<Resource> {
  79. vec![Resource::new(
  80. "dir",
  81. self.target.as_ref().parent().unwrap().to_string_lossy(),
  82. )]
  83. }
  84. fn provides(&self) -> Option<Vec<Resource>> {
  85. Some(vec![Resource::new(
  86. "dir",
  87. self.target.as_ref().to_str().unwrap(),
  88. )])
  89. }
  90. fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b> {
  91. Box::new(SymbolAction::new(runner, self))
  92. }
  93. fn into_action<'b>(self: Box<Self>, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b>
  94. where
  95. Self: 'b,
  96. {
  97. Box::new(OwnedSymbolAction::new(runner, *self))
  98. }
  99. }
  100. #[cfg(test)]
  101. mod test {}