commit:     eea598a20b2db5ecbe3975dc96885f529ae54c1c
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sat Mar  9 21:22:35 2024 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sat Mar  9 21:22:35 2024 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=eea598a2

__dyn_install: Record REPO_REVISIONS in build-info

Record REPO_REVISIONS as a json object that maps repo name to
revision for an ebuild's source repository and any repositories
that eclasses were inherited from:

$ cat /var/tmp/portage/sys-apps/portage-3.0.63/build-info/REPO_REVISIONS
{"gentoo": "34875e30e73e33d3597d1101cdf97dc22729b268"}

Ultimately the intention is to expose this information in binhost
metadata so that clients can select consistent revisions of source
repositories.

Bug: https://bugs.gentoo.org/924772
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 bin/phase-functions.sh                             |  1 +
 lib/_emerge/EbuildPhase.py                         | 46 ++++++++++++++++++++++
 .../package/ebuild/_config/special_env_vars.py     |  1 +
 3 files changed, 48 insertions(+)

diff --git a/bin/phase-functions.sh b/bin/phase-functions.sh
index ab130a3be5..9ff5554405 100644
--- a/bin/phase-functions.sh
+++ b/bin/phase-functions.sh
@@ -719,6 +719,7 @@ __dyn_install() {
 
        cp "${EBUILD}" "${PF}.ebuild"
        [[ -n "${PORTAGE_REPO_NAME}" ]]  && echo "${PORTAGE_REPO_NAME}" > 
repository
+       [[ -n ${PORTAGE_REPO_REVISIONS} ]] && echo "${PORTAGE_REPO_REVISIONS}" 
> REPO_REVISIONS
        if has nostrip ${FEATURES} ${PORTAGE_RESTRICT} || has strip 
${PORTAGE_RESTRICT}; then
                >> DEBUGBUILD
        fi

diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py
index b472803438..86a64be78e 100644
--- a/lib/_emerge/EbuildPhase.py
+++ b/lib/_emerge/EbuildPhase.py
@@ -4,6 +4,7 @@
 import functools
 import gzip
 import io
+import json
 import sys
 import tempfile
 
@@ -83,6 +84,50 @@ async def _setup_locale(settings):
                 raise AssertionError("C locale did not pass the test!")
 
 
+async def _setup_repo_revisions(settings):
+    repo_name = settings.configdict["pkg"].get("PORTAGE_REPO_NAME")
+    db = getattr(settings.mycpv, "_db", None)
+    if (
+        isinstance(db, portage.portdbapi)
+        and repo_name
+        and "PORTAGE_REPO_REVISIONS" not in settings.configdict["pkg"]
+    ):
+        inherits = frozenset(
+            (
+                await db.async_aux_get(
+                    settings.mycpv,
+                    ["INHERITED"],
+                    myrepo=repo_name,
+                )
+            )[0].split()
+        )
+        repo = db.repositories[repo_name]
+        ec_dict = repo.eclass_db.get_eclass_data(inherits)
+        referenced_repos = {repo.name: repo}
+        for ec_info in ec_dict.values():
+            ec_repo = db.repositories.get_repo_for_location(
+                os.path.dirname(os.path.dirname(ec_info.location))
+            )
+            referenced_repos.setdefault(ec_repo.name, ec_repo)
+        repo_revisions = {}
+        for repo_ref in referenced_repos.values():
+            if repo_ref.sync_type:
+                sync = 
portage.sync.module_controller.get_class(repo_ref.sync_type)()
+                try:
+                    # TODO: Wait for subprocesses asynchronously here.
+                    status, repo_revision = sync.retrieve_head(
+                        options={"repo": repo_ref}
+                    )
+                except NotImplementedError:
+                    pass
+                else:
+                    if status == os.EX_OK:
+                        repo_revisions[repo_ref.name] = repo_revision.strip()
+        settings.configdict["pkg"]["PORTAGE_REPO_REVISIONS"] = json.dumps(
+            repo_revisions, ensure_ascii=False, sort_keys=True
+        )
+
+
 class EbuildPhase(CompositeTask):
     __slots__ = ("actionmap", "fd_pipes", "phase", "settings") + 
("_ebuild_lock",)
 
@@ -120,6 +165,7 @@ class EbuildPhase(CompositeTask):
     async def _async_start(self):
 
         await _setup_locale(self.settings)
+        await _setup_repo_revisions(self.settings)
 
         need_builddir = self.phase not in 
EbuildProcess._phases_without_builddir
 

diff --git a/lib/portage/package/ebuild/_config/special_env_vars.py 
b/lib/portage/package/ebuild/_config/special_env_vars.py
index 6020029e35..1a66192c96 100644
--- a/lib/portage/package/ebuild/_config/special_env_vars.py
+++ b/lib/portage/package/ebuild/_config/special_env_vars.py
@@ -165,6 +165,7 @@ environ_whitelist = frozenset(
         "PORTAGE_PYTHON",
         "PORTAGE_PYTHONPATH",
         "PORTAGE_QUIET",
+        "PORTAGE_REPO_REVISIONS",
         "PORTAGE_REPO_NAME",
         "PORTAGE_REPOSITORIES",
         "PORTAGE_RESTRICT",

Reply via email to