Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion kernel_patches_daemon/branch_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ def __init__(
app_auth: Optional[Auth.AppInstallationAuth] = None,
email: Optional[EmailConfig] = None,
http_retries: Optional[int] = None,
mirror_dir: Optional[str] = None,
) -> None:
super().__init__(
repo_url=repo_url,
Expand All @@ -559,6 +560,7 @@ def __init__(
self.email = email

self.log_extractor = log_extractor
self.mirror_dir = mirror_dir
self.ci_repo_url = ci_repo_url
self.ci_repo_dir = _uniq_tmp_folder(ci_repo_url, ci_branch, base_directory)
self.ci_branch = ci_branch
Expand Down Expand Up @@ -682,9 +684,22 @@ def do_sync(self) -> None:
def full_sync(self, path: str, url: str, branch: str) -> git.Repo:
logging.info(f"Doing full clone from {redact_url(url)}, branch: {branch}")

multi_opts: Optional[List[str]] = None
if self.mirror_dir:
upstream_name = os.path.basename(self.upstream_url)
reference_path = os.path.join(self.mirror_dir, upstream_name)
fallback = os.path.join(self.mirror_dir, "linux.git")
if not os.path.exists(reference_path) and os.path.exists(fallback):
reference_path = fallback
if os.path.exists(reference_path):
multi_opts = ["--reference", reference_path]

with HistogramMetricTimer(git_clone_duration, {"branch": branch}):
shutil.rmtree(path, ignore_errors=True)
repo = git.Repo.clone_from(url, path)
if multi_opts:
repo = git.Repo.clone_from(url, path, multi_options=multi_opts)
else:
repo = git.Repo.clone_from(url, path)
_reset_repo(repo, f"origin/{branch}")

git_clone_counter.add(1, {"branch": branch})
Expand Down
2 changes: 2 additions & 0 deletions kernel_patches_daemon/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class KPDConfig:
branches: Dict[str, BranchConfig]
tag_to_branch_mapping: Dict[str, List[str]]
base_directory: str
mirror_dir: Optional[str] = None

@classmethod
def from_json(cls, json: Dict) -> "KPDConfig":
Expand Down Expand Up @@ -203,6 +204,7 @@ def from_json(cls, json: Dict) -> "KPDConfig":
for name, json_config in json["branches"].items()
},
base_directory=json["base_directory"],
mirror_dir=json.get("mirror_dir"),
)

@classmethod
Expand Down
1 change: 1 addition & 0 deletions kernel_patches_daemon/github_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def __init__(
ci_branch=branch_config.ci_branch,
log_extractor=_log_extractor_from_project(kpd_config.patchwork.project),
base_directory=kpd_config.base_directory,
mirror_dir=kpd_config.mirror_dir,
http_retries=http_retries,
github_oauth_token=branch_config.github_oauth_token,
app_auth=github_app_auth_from_branch_config(branch_config),
Expand Down
20 changes: 20 additions & 0 deletions tests/test_branch_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
TEST_CI_REPO_URL = f"https://user:[email protected]/ci-org/{TEST_CI_REPO}"
TEST_CI_BRANCH = "test_ci_branch"
TEST_BASE_DIRECTORY = "/repos"
TEST_MIRROR_DIRECTORY = "/mirror"
TEST_BRANCH = "test-branch"
TEST_CONFIG: Dict[str, Any] = {
"version": 2,
Expand Down Expand Up @@ -124,6 +125,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
"ci_branch": TEST_CI_BRANCH,
"log_extractor": DefaultGithubLogExtractor(),
"base_directory": TEST_BASE_DIRECTORY,
"mirror_dir": None,
}
presets.update(kwargs)

Expand Down Expand Up @@ -464,6 +466,24 @@ def test_fetch_repo_path_exists_git_exception(self) -> None:
self._bw.fetch_repo(*fetch_params)
fr.assert_called_once_with(*fetch_params)

def test_full_sync_with_mirror_dir(self) -> None:
bw = BranchWorkerMock(mirror_dir=TEST_MIRROR_DIRECTORY)
reference = os.path.join(
TEST_MIRROR_DIRECTORY, os.path.basename(TEST_UPSTREAM_REPO_URL)
)
with (
patch("kernel_patches_daemon.branch_worker.os.path.exists") as exists,
patch("kernel_patches_daemon.branch_worker.shutil.rmtree") as rm,
):
exists.side_effect = lambda p: p == reference
bw.upstream_url = TEST_UPSTREAM_REPO_URL
bw.full_sync("somepath", "giturl", "branch")
self._git_repo_mock.clone_from.assert_called_once_with(
"giturl",
"somepath",
multi_options=["--reference", reference],
)

def test_expire_branches(self) -> None:
"""Only the branch that matches pattern and is expired should be deleted"""
not_expired_time = datetime.fromtimestamp(3 * BRANCH_TTL)
Expand Down
1 change: 1 addition & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,6 @@ def test_valid(self) -> None:
),
},
base_directory="/repos",
mirror_dir=None,
)
self.assertEqual(config, expected_config)
7 changes: 7 additions & 0 deletions tests/test_github_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ class TestCase:
gh.workers[TEST_BRANCH].ci_repo_dir.startswith(case.prefix),
)

def test_init_with_mirror_dir(self) -> None:
config = copy.copy(TEST_CONFIG)
config["mirror_dir"] = "/mirror"
kpd_config = KPDConfig.from_json(config)
gh = GithubSyncMock(kpd_config=kpd_config)
self.assertEqual("/mirror", gh.workers[TEST_BRANCH].mirror_dir)

def test_close_existing_prs_for_series(self) -> None:
matching_pr_mock = MagicMock()
matching_pr_mock.title = "matching"
Expand Down