diff --git a/repo_cloner/lib/repo_tool.py b/repo_cloner/lib/repo_tool.py index 20658e0..3fdd262 100644 --- a/repo_cloner/lib/repo_tool.py +++ b/repo_cloner/lib/repo_tool.py @@ -95,6 +95,7 @@ class RepoTool: _initialized: bool = False _bare: bool = False _path: str = "" + _last_fetch_data = [] def __init__(self, path: str): log.info(f"Initializing repository at {path}") @@ -121,6 +122,16 @@ class RepoTool: def path(self) -> str: return self._path + def __check_initialized(self): + def inner(*args): + fake_self: RepoTool = args[0] + if not fake_self._initialized: + log.critical(f"Repo {fake_self.path} is not initialized!") + return False + return self(*args) + + return inner + def clone(self, url: str) -> bool: if self._initialized: log.warning(f"Trying to clone to initialized repository!") @@ -132,3 +143,21 @@ class RepoTool: self._bare = self._repo.bare return True + + @__check_initialized + def fetch(self) -> bool: + log.info("Fetching repo state") + if not len(self._repo.remotes): + log.warning(f"Repo: {self._path} does not contain any remotes!") + return False + # fetch all remotes + remote = self._repo.remotes[0] + log.debug(f"Fetching remote: {remote.name} url: {next(remote.urls)}") + self._last_fetch_data = remote.fetch( + "+refs/heads/*:refs/heads/*", + progress = GitRemoteProgress(), + kill_after_timeout = 60, + prune = True + ) + log.debug("Fetch finished!") + return True diff --git a/tests/lib/test_repo_tool.py b/tests/lib/test_repo_tool.py index 0438f3b..15baabe 100644 --- a/tests/lib/test_repo_tool.py +++ b/tests/lib/test_repo_tool.py @@ -1,4 +1,6 @@ import logging + +import git import pytest from cloner_test_fixtures import support_data_path from pathlib import Path @@ -67,6 +69,15 @@ def test_clone_initialized_repo(tmp_path, caplog, support_data_path): assert r.message == "Trying to clone to initialized repository!" +def test_check_initialized(tmp_path, monkeypatch, caplog): + # hard testing directly, testing via fetch + rt = RepoTool(tmp_path.as_posix()) + assert not rt.initialized + assert not rt.fetch() + assert caplog.records[1].levelname == "CRITICAL" + assert caplog.records[1].message == f"Repo {tmp_path.as_posix()} is not initialized!" + + def test_clone_okay(tmp_path, caplog, support_data_path): rt = RepoTool(tmp_path.as_posix()) assert not rt.initialized @@ -105,3 +116,46 @@ def test_clone_okay(tmp_path, caplog, support_data_path): assert compressing_cnt >= 2 assert receiving_cnt >= 2 assert resolving_cnt >= 2 + + +def test_fetch_uninitialized(tmp_path, caplog): + repo_a = tmp_path.joinpath("A.git") + repo_b = tmp_path.joinpath("B.git") + + repo_a.mkdir() + rt = RepoTool(repo_a.as_posix()) + assert not rt.initialized + assert not rt.fetch() + + assert f"Repo {repo_a.as_posix()} is not initialized!" + + +def test_fetch_no_remotes(tmp_path, caplog): + repo_a = tmp_path.joinpath("A.git") + + git.Repo().init(repo_a.as_posix()) + + rt = RepoTool(repo_a.as_posix()) + assert not rt.fetch() + assert caplog.records[0].levelname == "WARNING" + assert caplog.records[0].message == f"Repo: {repo_a.as_posix()} does not contain any remotes!" + + +def test_fetch_ok(tmp_path): + repo_a = tmp_path.joinpath("A.git") + repo_b = tmp_path.joinpath("B.git") + + r = git.Repo().init(repo_a.as_posix()) + + rt = RepoTool(repo_b.as_posix()) + assert rt.clone(repo_a.as_uri()) + + # new file + repo_a.joinpath(".gitignore").touch() + # commit it + r.git.add(".gitignore") + r.git.commit(message = "Test Commit", author = "Tester ") + hash = r.commit("master").hexsha + + assert rt.fetch() + assert rt._repo.commit(hash)