diff --git a/src/git.rs b/src/git.rs index 317d016..724824f 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,36 +1,106 @@ use std::path::Path; use std::process::Command; -use url::Url; - pub struct Git; impl Git { - pub fn clone(url: &Url, dest: &Path) { + pub fn clone(url: &str, dest: &Path, dir: &str) { let dest = dest.canonicalize().unwrap(); let mut child = Command::new("git") - .args(["clone", url.as_str()]) + .args(["clone", url, dir]) .current_dir(dest) .spawn() .expect("unable to obtain Docker version"); child.wait().unwrap(); } - pub fn pull(dest: &Path, branch: &str) { - let dest = dest.canonicalize().unwrap(); - Command::new("git") - .current_dir(dest) + pub fn pull(repo: &Path, branch: &str) { + let repo = repo.canonicalize().unwrap(); + let mut c = Command::new("git") + .current_dir(repo) .args(["pull", "origin", branch]) .spawn() .expect("unable to obtain Docker version"); + c.wait().unwrap(); } - pub fn push(branch: &str, dest: &Path) { - let dest = dest.canonicalize().unwrap(); - let output = Command::new("git") - .current_dir(dest) + pub fn push(branch: &str, repo: &Path) { + let repo = repo.canonicalize().unwrap(); + let mut child = Command::new("git") + .current_dir(repo) .args(["push", "origin", branch]) .spawn() .expect("unable to get logs"); + child.wait().unwrap(); + } + + pub fn checkout_commit(commit: &str, repo: &Path) { + let repo = repo.canonicalize().unwrap(); + let mut child = Command::new("git") + .current_dir(repo) + .args(["checkout", commit]) + .spawn() + .expect("unable to get logs"); + child.wait().unwrap(); + } + + pub fn files_changed_from_previous_commit(repo: &Path) -> Vec { + let repo = repo.canonicalize().unwrap(); + let out = Command::new("git") + .current_dir(repo) + .args(["--no-pager", "diff", "--name-only", "HEAD^"]) + .output() + .expect("unable to get logs"); + let out = String::from_utf8(out.stdout).unwrap(); + let mut s = Vec::default(); + for f in out.lines() { + s.push(f.trim().to_owned()) + } + s + } +} + +#[cfg(test)] +mod tests { + use std::fs; + + use super::*; + use mktemp::Temp; + + #[test] + fn git_works() { + let tmp = Temp::new_dir().unwrap(); + let tmp = tmp.as_path(); + let upstream = "/tmp/git_cmd_init_tmp/repo"; + let commits_file = "/tmp/git_cmd_init_tmp/commits"; + let script = "./tests/git_cmd_init.sh"; + + Command::new(script).args(["init"]).output().unwrap(); + + Git::clone(upstream, tmp, "git_works"); + let repo = tmp.join("git_works"); + let contents = fs::read_to_string(repo.join("2_commit.txt")).unwrap(); + let commits = fs::read_to_string(commits_file).unwrap(); + assert_eq!(commits.lines().into_iter().count(), 2); + assert!(contents.contains("bar")); + assert!(!contents.contains("new commit")); + + let first_commit = commits.lines().last().unwrap(); + + Git::checkout_commit(first_commit, repo.as_path()); + assert!(!repo.join("2_commit.txt").exists()); + + Git::checkout_commit("master", repo.as_path()); + assert!(repo.join("2_commit.txt").exists()); + + Command::new(script).args(["update"]).output().unwrap(); + Git::pull(&repo, "master"); + + let new_commits = fs::read_to_string(commits_file).unwrap(); + assert_eq!(new_commits.lines().into_iter().count(), 3); + + let changes = Git::files_changed_from_previous_commit(&repo); + assert_eq!(changes.len(), 1); + assert_eq!(changes.get(0).unwrap(), "3_commit.txt"); } } diff --git a/tests/git_cmd_init.sh b/tests/git_cmd_init.sh new file mode 100755 index 0000000..6cde8e8 --- /dev/null +++ b/tests/git_cmd_init.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -euo pipefail + +readonly DIR=/tmp/git_cmd_init_tmp +readonly REPO=$DIR/repo + +commit() { + git add --all + git commit \ + --author="ftest-test-util-script " \ + --message="$1" +} + +write_commits_to_file() { + pushd $REPO + popd + rm -rf $DIR/commits + git log --pretty=oneline | cut -d ' ' -f 1 > $DIR/commits +} + + + +init() { + rm -rf $DIR || true + mkdir -p $REPO + cd $REPO + git init + echo "foo" > 1_commit.txt + commit "first commit" + echo "bar" > 2_commit.txt + commit "second commit" + write_commits_to_file +} + + +update() { + cd $REPO + echo "bar" >> 3_commit.txt + commit "new commit" + write_commits_to_file +} + +$@ + +exit 0