Cloner: sync - check fingerprint before costy discovery
Signed-off-by: Václav Valíček <valicek1994@gmail.com>
This commit is contained in:
parent
5ca24960c3
commit
d74c67d4f6
|
@ -1,9 +1,9 @@
|
||||||
from repo_cloner.lib import gen_repo_hashed_name
|
from repo_cloner.lib import gen_repo_hashed_name
|
||||||
from repo_cloner.lib import DirNotFoundError
|
from repo_cloner.lib import DirNotFoundError
|
||||||
from repo_cloner.lib import ClonerConfig, DiskStoredList, RepoDirStructure, RepoTool
|
from repo_cloner.lib import ClonerConfig, DiskStoredList, RepoDirStructure, RepoTool, DetectedCommit, Detector
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional, Callable
|
||||||
from time import time
|
from time import time
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
@ -119,11 +119,17 @@ class Cloner:
|
||||||
if not self._config.cloner_submodules:
|
if not self._config.cloner_submodules:
|
||||||
return self._repo.fetch()
|
return self._repo.fetch()
|
||||||
|
|
||||||
|
fingerprint = self._repo.repo_fingerprint
|
||||||
|
|
||||||
# recursive now
|
# recursive now
|
||||||
if not self._repo.fetch():
|
if not self._repo.fetch():
|
||||||
log.critical(f"Repo fetch failed for {self._config.cloner_project_name}")
|
log.critical(f"Repo fetch failed for {self._config.cloner_project_name}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if fingerprint == self._repo.repo_fingerprint:
|
||||||
|
log.info(f"Repo fingerpring unchanged - submodule discovery skipped")
|
||||||
|
return True
|
||||||
|
|
||||||
log.debug(f"Loading submodules.cache")
|
log.debug(f"Loading submodules.cache")
|
||||||
submodules = DiskStoredList(os.path.join(self.__submodule_cache, "submodules.cache"))
|
submodules = DiskStoredList(os.path.join(self.__submodule_cache, "submodules.cache"))
|
||||||
log.debug(f"Loaded submodules.cache - {len(submodules)} items")
|
log.debug(f"Loaded submodules.cache - {len(submodules)} items")
|
||||||
|
@ -207,3 +213,7 @@ class Cloner:
|
||||||
@property
|
@property
|
||||||
def detector_enabled(self) -> bool:
|
def detector_enabled(self) -> bool:
|
||||||
return os.path.exists(os.path.join(self._dirs.conf_dir, self.__detector_cfg))
|
return os.path.exists(os.path.join(self._dirs.conf_dir, self.__detector_cfg))
|
||||||
|
|
||||||
|
def run_detector(self, callback: Callable[[DetectedCommit], None]):
|
||||||
|
detector = Detector(self.__main_repo_path, self._dirs.cache_dir, self._config.cloner_project_name)
|
||||||
|
detector.run(callback)
|
||||||
|
|
|
@ -309,6 +309,7 @@ def test_submodules_sync_succeed(cloner_dir_with_config, caplog):
|
||||||
'initialized': PropertyMock(side_effect = [True, False, True, True, True]),
|
'initialized': PropertyMock(side_effect = [True, False, True, True, True]),
|
||||||
'fetch': MagicMock(return_value = True),
|
'fetch': MagicMock(return_value = True),
|
||||||
'clone': MagicMock(return_value = True),
|
'clone': MagicMock(return_value = True),
|
||||||
|
'repo_fingerprint': PropertyMock(side_effect = ["fp1", "fp2", "fp3"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
with patch.multiple("repo_cloner.lib.cloner.RepoTool", **mocks):
|
with patch.multiple("repo_cloner.lib.cloner.RepoTool", **mocks):
|
||||||
|
@ -320,6 +321,33 @@ def test_submodules_sync_succeed(cloner_dir_with_config, caplog):
|
||||||
assert repo_cloner.lib.cloner.RepoTool.clone.call_count == 1
|
assert repo_cloner.lib.cloner.RepoTool.clone.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_submodules_sync_unchanged_main_repo(cloner_dir_with_config, caplog):
|
||||||
|
caplog.set_level(0)
|
||||||
|
cloner_dir_with_config.joinpath("cache", "submodules").mkdir(parents = True)
|
||||||
|
cloner_dir_with_config.joinpath("cache", "submodules", "submodules.cache") \
|
||||||
|
.write_text("https://git.hosting:previous/submodule.git")
|
||||||
|
ds = MockDirStruct(cloner_dir_with_config)
|
||||||
|
ds.config.cloner_repo_url = "https://git.hosting:namespace/whatever.git"
|
||||||
|
ds.config.cloner_submodules = True
|
||||||
|
|
||||||
|
# mock almost everything
|
||||||
|
mocks = {
|
||||||
|
'initialized': PropertyMock(side_effect = [True, False, True, True, True]),
|
||||||
|
'fetch': MagicMock(return_value = True),
|
||||||
|
'clone': MagicMock(return_value = True),
|
||||||
|
# fingerprint is same for both queries, so nothing is fetched/synced afterwards
|
||||||
|
'repo_fingerprint': PropertyMock(return_value = "fp1"),
|
||||||
|
}
|
||||||
|
|
||||||
|
with patch.multiple("repo_cloner.lib.cloner.RepoTool", **mocks):
|
||||||
|
Cloner.check_submodules_repo = my_check_submodules_repo
|
||||||
|
cl = Cloner(ds)
|
||||||
|
assert cl.sync()
|
||||||
|
|
||||||
|
assert repo_cloner.lib.cloner.RepoTool.fetch.call_count == 1
|
||||||
|
assert repo_cloner.lib.cloner.RepoTool.clone.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
def test_submodules_sync_one_fail(cloner_dir_with_config, caplog):
|
def test_submodules_sync_one_fail(cloner_dir_with_config, caplog):
|
||||||
cloner_dir_with_config.joinpath("cache", "submodules").mkdir(parents = True)
|
cloner_dir_with_config.joinpath("cache", "submodules").mkdir(parents = True)
|
||||||
cloner_dir_with_config.joinpath("cache", "submodules", "submodules.cache") \
|
cloner_dir_with_config.joinpath("cache", "submodules", "submodules.cache") \
|
||||||
|
@ -335,6 +363,7 @@ def test_submodules_sync_one_fail(cloner_dir_with_config, caplog):
|
||||||
'initialized': PropertyMock(return_value = True),
|
'initialized': PropertyMock(return_value = True),
|
||||||
'fetch': MagicMock(side_effect = [True, True, True, False, True]),
|
'fetch': MagicMock(side_effect = [True, True, True, False, True]),
|
||||||
'clone': MagicMock(return_value = True),
|
'clone': MagicMock(return_value = True),
|
||||||
|
'repo_fingerprint': PropertyMock(side_effect = ["fp1", "fp2", "fp3"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
with patch.multiple("repo_cloner.lib.cloner.RepoTool", **mocks):
|
with patch.multiple("repo_cloner.lib.cloner.RepoTool", **mocks):
|
||||||
|
@ -458,6 +487,7 @@ def test_clone_recursive(tmp_path, path_repo_base, caplog):
|
||||||
patch_clone_recursive.assert_called_with(
|
patch_clone_recursive.assert_called_with(
|
||||||
'https://repo', tmp_path.joinpath('cache', 'submodules').as_posix(), scan_depth = None)
|
'https://repo', tmp_path.joinpath('cache', 'submodules').as_posix(), scan_depth = None)
|
||||||
|
|
||||||
|
|
||||||
def test_detector_enabled(cloner_dir_with_config):
|
def test_detector_enabled(cloner_dir_with_config):
|
||||||
ds = MockDirStruct(cloner_dir_with_config)
|
ds = MockDirStruct(cloner_dir_with_config)
|
||||||
ds.config.cloner_repo_url = "http://mock"
|
ds.config.cloner_repo_url = "http://mock"
|
||||||
|
@ -465,4 +495,3 @@ def test_detector_enabled(cloner_dir_with_config):
|
||||||
assert not cl.detector_enabled
|
assert not cl.detector_enabled
|
||||||
Path(cloner_dir_with_config).joinpath("config", "detector.cfg").touch()
|
Path(cloner_dir_with_config).joinpath("config", "detector.cfg").touch()
|
||||||
assert cl.detector_enabled
|
assert cl.detector_enabled
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user