feat: git cmd and tests

This commit is contained in:
Aravinth Manivannan 2023-09-27 17:18:41 +05:30
parent 17efcac145
commit 44a97e8928
Signed by: realaravinth
GPG key ID: F8F50389936984FF
2 changed files with 128 additions and 12 deletions

View file

@ -1,36 +1,106 @@
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use url::Url;
pub struct Git; pub struct Git;
impl 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 dest = dest.canonicalize().unwrap();
let mut child = Command::new("git") let mut child = Command::new("git")
.args(["clone", url.as_str()]) .args(["clone", url, dir])
.current_dir(dest) .current_dir(dest)
.spawn() .spawn()
.expect("unable to obtain Docker version"); .expect("unable to obtain Docker version");
child.wait().unwrap(); child.wait().unwrap();
} }
pub fn pull(dest: &Path, branch: &str) { pub fn pull(repo: &Path, branch: &str) {
let dest = dest.canonicalize().unwrap(); let repo = repo.canonicalize().unwrap();
Command::new("git") let mut c = Command::new("git")
.current_dir(dest) .current_dir(repo)
.args(["pull", "origin", branch]) .args(["pull", "origin", branch])
.spawn() .spawn()
.expect("unable to obtain Docker version"); .expect("unable to obtain Docker version");
c.wait().unwrap();
} }
pub fn push(branch: &str, dest: &Path) { pub fn push(branch: &str, repo: &Path) {
let dest = dest.canonicalize().unwrap(); let repo = repo.canonicalize().unwrap();
let output = Command::new("git") let mut child = Command::new("git")
.current_dir(dest) .current_dir(repo)
.args(["push", "origin", branch]) .args(["push", "origin", branch])
.spawn() .spawn()
.expect("unable to get logs"); .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<String> {
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");
} }
} }

46
tests/git_cmd_init.sh Executable file
View file

@ -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 <ftest-test-util-script@example.org>" \
--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