#!/usr/bin/env python3 """ Tests for git_oh script """ import datetime import gc import os import random import shutil import tempfile import unittest import git import git_oh class TestGitIterations(unittest.TestCase): """ Testing iterator on git commits """ def setUp(self): self.repo_path = tempfile.mkdtemp(prefix="git_oh_test_") self.repo = git.Repo.init(self.repo_path) self.actors = [git.Actor(f"User{i:d}", f"user{i:d}@localhost") for i in range(8)] def tearDown(self): shutil.rmtree(self.repo_path) def test_metadata(self): """ Fetch commits and their metadata in a simple git repository """ fromisoformat = datetime.datetime.fromisoformat commit_date_fmt = "2022-12-13T23:32:2%d+0200" commits = [ self.git_commit_mod(author=self.actors[0], commit_date=fromisoformat(commit_date_fmt % i)) for i in range(10)] found_commits = list(git_oh.iter_commits(self.repo)) set_a = {c.hexsha for c in commits} set_b = {c.hexsha for c in found_commits} self.assertEqual(set_a, set_b) for commit in found_commits: self.assertEqual(commit.author, self.actors[0]) self.assertLessEqual(commit.committed_datetime, fromisoformat(commit_date_fmt % 9)) self.assertGreaterEqual(commit.committed_datetime, fromisoformat(commit_date_fmt % 0)) def test_branches(self): """ Fetch commits from a repo with mutliple branches """ commits = [self.git_commit_mod(author=self.actors[0]) for _ in range(10)] self.repo.git.checkout("HEAD", b="new_branch") commits += [self.git_commit_mod(author=self.actors[0]) for _ in range(10)] self.repo.git.checkout("HEAD", b="another_branch") commits += [self.git_commit_mod(author=self.actors[0]) for _ in range(10)] self.repo.git.checkout("new_branch") found_commits = {commit.hexsha for commit in git_oh.iter_commits(self.repo)} commits = {commit.hexsha for commit in commits} self.assertEqual(commits, found_commits) def test_remote(self): """ Testing TempRemoteRepo class commit fetch __iter__ method """ commits = {self.git_commit_mod(author=self.actors[0]).hexsha for _ in range(10)} repo = git_oh.TempRemoteRepo(f"file://{self.repo_path:s}") found_commits = {commit.hexsha for commit in repo} self.assertEqual(commits, found_commits) def test_remote_cleanup(self): """ Testing TempRemoteRepo class cleanup """ repo = git_oh.TempRemoteRepo(f"file://{self.repo_path:s}") tmppath = repo.temppath _ = list(repo) self.assertTrue(os.path.isdir(tmppath)) del repo gc.collect() # asking gc to call repo.__del__() self.assertFalse(os.path.isdir(tmppath)) def test_remote_branches(self): """ Testing TempRemoteRepo branch commit fetch """ commits = [] for i in range(5): commits += [self.git_commit_mod(author=self.actors[0]) for _ in range(10)] self.repo.git.checkout("HEAD", b=f"branch-{i:d}") repo = git_oh.TempRemoteRepo(f"file://{self.repo_path:s}") found_commits = {commit.hexsha for commit in repo} commits = {commit.hexsha for commit in commits} self.assertEqual(commits, found_commits) def git_commit_mod(self, msg="new commit", filename="foo.txt", **commit_kwargs): """ Add a random modification to repository and commit them Arguments : - msg : commit message - filename : the filename to modify/add/commit - **commit_kwargs : see help(git.index.base.IndexFile.commit) Returns : - the commit instance """ with open(os.path.join(self.repo_path, filename), "w+", encoding="utf-8") as repo_fp: repo_fp.write(random.choices("abcdef")[0]) self.repo.index.add([filename]) return self.repo.index.commit(msg, **commit_kwargs) if __name__ == "__main__": unittest.main()