commit: 79d03d7823011bd19de06fa510a5d599eded87ed Author: Florian Schmaus <flow <AT> gentoo <DOT> org> AuthorDate: Tue Oct 24 07:59:45 2023 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat Nov 11 02:55:28 2023 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=79d03d78
sync: git: add sync-git-verify-max-age-days option Signed-off-by: Florian Schmaus <flow <AT> gentoo.org> Closes: https://github.com/gentoo/portage/pull/1158 Signed-off-by: Sam James <sam <AT> gentoo.org> NEWS | 6 ++++ lib/portage/sync/modules/git/__init__.py | 1 + lib/portage/sync/modules/git/git.py | 48 ++++++++++++++++++++++++++++++++ man/portage.5 | 4 +++ 4 files changed, 59 insertions(+) diff --git a/NEWS b/NEWS index 2a2c6bd7f0..1e589c1f8d 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,12 @@ Release notes take the form of the following optional categories: * Bug fixes * Cleanups +portage-3.0.56 (UNRELEASED) +-------------- + +Features: +* sync: git: Add sync-git-verify-max-age-days option. + portage-3.0.55 (2023-11-06) -------------- diff --git a/lib/portage/sync/modules/git/__init__.py b/lib/portage/sync/modules/git/__init__.py index ef32a9da06..121494215c 100644 --- a/lib/portage/sync/modules/git/__init__.py +++ b/lib/portage/sync/modules/git/__init__.py @@ -77,6 +77,7 @@ module_spec = { "sync-git-pull-env", "sync-git-pull-extra-opts", "sync-git-verify-commit-signature", + "sync-git-verify-max-age-days", ), } }, diff --git a/lib/portage/sync/modules/git/git.py b/lib/portage/sync/modules/git/git.py index 48109b7844..cf9ad1c134 100644 --- a/lib/portage/sync/modules/git/git.py +++ b/lib/portage/sync/modules/git/git.py @@ -4,12 +4,14 @@ import logging import re import subprocess +import datetime import portage from portage import os from portage.util import writemsg_level, shlex_split from portage.util.futures import asyncio from portage.output import create_color_func, EOutput +from portage.const import TIMESTAMP_FORMAT good = create_color_func("GOOD") bad = create_color_func("BAD") @@ -436,6 +438,52 @@ class GitSync(NewBase): return (os.EX_OK, current_rev != previous_rev) def verify_head(self, revision="-1") -> bool: + max_age_days = self.repo.module_specific_options.get( + "sync-git-verify-max-age-days", "" + ) + if max_age_days: + try: + max_age_days = int(max_age_days) + if max_age_days <= 0: + raise ValueError(max_age_days) + except ValueError: + writemsg_level( + f"!!! sync-git-max-age-days must be a positive non-zero integer: {max_age_days}\n", + level=logging.ERROR, + noiselevel=-1, + ) + return False + show_timestamp_chk_file_cmd = [ + self.bin_command, + "show", + f"{revision}:metadata/timestamp.chk", + ] + try: + timestamp_chk = portage._unicode_decode( + subprocess.check_output( + show_timestamp_chk_file_cmd, + cwd=portage._unicode_encode(self.repo.location), + ) + ).strip() + except subprocess.CalledProcessError as e: + writemsg_level( + f"!!! {show_timestamp_chk_file_cmd} failed with {e.returncode}", + level=logging.ERROR, + noiselevel=-1, + ) + return False + timestamp = datetime.datetime.strptime(timestamp_chk, TIMESTAMP_FORMAT) + max_timestamp_age = datetime.datetime.now() - datetime.timedelta( + days=max_age_days + ) + if timestamp < max_timestamp_age: + writemsg_level( + f"!!! timestamp (from timestamp.chk) {timestamp} is older than max age {max_timestamp_age}\n", + level=logging.ERROR, + noiselevel=-1, + ) + return False + if self.repo.module_specific_options.get( "sync-git-verify-commit-signature", "false" ).lower() not in ("true", "yes"): diff --git a/man/portage.5 b/man/portage.5 index 91c3ffdb45..dae4d47206 100644 --- a/man/portage.5 +++ b/man/portage.5 @@ -1071,6 +1071,10 @@ Extra options to give to git when updating repository (git pull). Require the top commit in the repository to contain a good OpenPGP signature. Defaults to no, false. .TP +.B sync\-git\-verify\-max\-age\-days +Warn if repository is older than the specified number of days. Disabled +when 0. Defaults to disabled. +.TP .B sync\-hooks\-only\-on\-change = yes|no|true|false If set to true, then sync of a given repository will not trigger postsync hooks unless hooks would have executed for a master repository or the
