From: ecordonnier@snap.com
To: openembedded-core@lists.openembedded.org
Cc: Etienne Cordonnier <ecordonnier@snap.com>
Subject: [PATCH v2 1/3] archiver.bbclass: archive shallow git sources which have no clone
Date: Fri, 30 Oct 2026 18:45:34 +0100 [thread overview]
Message-ID: <20261030174536.2724008-2-ecordonnier@snap.com> (raw)
In-Reply-To: <20261030174536.2724008-1-ecordonnier@snap.com>
From: Etienne Cordonnier <ecordonnier@snap.com>
In the original mode, do_ar_original archives a source if the fetcher's
localpath is a file, or a directory (which is unpacked and tarred). For git,
localpath is the clone in DL_DIR/git2. A shallow fetch (BB_GIT_SHALLOW) can
use the gitshallow tarball (ud.fullshallow) without creating the clone: since
bitbake commit 457288b2f ("fetch2/git: Add support for fast initial shallow
fetch") this is what a shallow fetch does by default, and it also happens when
the shallow tarball is fetched from a mirror. In this case, the source was
silently skipped and not archived at all.
Treat this case like a directory source, as unpack() populates the
directory from the shallow tarball. Use the same check as unpack()
(clonedir_need_update()), so that the case of an out of date clone, where
unpack() also uses the shallow tarball, is handled as well.
AI-Generated: Claude Sonnet 5.5
Signed-off-by: Etienne Cordonnier <ecordonnier@snap.com>
---
meta/classes/archiver.bbclass | 8 +++-
meta/lib/oeqa/selftest/cases/archiver.py | 48 ++++++++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/meta/classes/archiver.bbclass b/meta/classes/archiver.bbclass
index 0400d6e373..f6cca35186 100644
--- a/meta/classes/archiver.bbclass
+++ b/meta/classes/archiver.bbclass
@@ -204,10 +204,16 @@ python do_ar_original() {
fetch = bb.fetch.Fetch(urls, ld)
tarball_suffix = {}
for url in fetch.urls:
+ ud = fetch.ud[url]
local = fetch.localpath(url).rstrip("/");
+ # A shallow git fetch which used the shallow tarball has no up to date
+ # clone, which is what localpath() points to. unpack() then uses the
+ # shallow tarball, using the same check as here.
+ shallow = getattr(ud, 'shallow', False) and os.path.isfile(ud.fullshallow) \
+ and ud.method.clonedir_need_update(ud, ld)
if os.path.isfile(local):
shutil.copy(local, ar_outdir)
- elif os.path.isdir(local):
+ elif os.path.isdir(local) or shallow:
tmpdir = tempfile.mkdtemp(dir=d.getVar('ARCHIVER_WORKDIR'))
fetch.unpack(tmpdir, (url,))
# To handle recipes with more than one source, we add the "name"
diff --git a/meta/lib/oeqa/selftest/cases/archiver.py b/meta/lib/oeqa/selftest/cases/archiver.py
index 8c5aa75e9b..84f13839c9 100644
--- a/meta/lib/oeqa/selftest/cases/archiver.py
+++ b/meta/lib/oeqa/selftest/cases/archiver.py
@@ -7,6 +7,8 @@
import os
import glob
import re
+import shutil
+import tarfile
from oeqa.utils.commands import bitbake, get_bb_vars
from oeqa.selftest.case import OESelftestTestCase
@@ -176,6 +178,52 @@ class Archiver(OESelftestTestCase):
self._test_archiver_mode('original', 'ed-1.21.1.tar.lz')
+ def test_archiver_mode_original_git_shallow(self):
+ """
+ Test that the archiver archives a shallow git source with
+ `ARCHIVER_MODE[src] = "original"` when only the shallow tarball is
+ available, but not the clone. This is what happens with the fast
+ initial shallow fetch, or when the shallow tarball is fetched from a
+ mirror.
+ """
+ target = 'gitrepotest'
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "original"\n'
+ features += 'BB_GIT_SHALLOW = "1"\n'
+ features += 'BB_GENERATE_SHALLOW_TARBALLS = "1"\n'
+ features += 'DL_DIR = "${TOPDIR}/downloads-shallow"\n'
+ self.write_config(features)
+
+ # Fetch to create the shallow tarball, then remove the clone if the
+ # fetcher fell back to a full clone, so that the second fetch has to
+ # use the shallow tarball. cleansstate makes sure that the archive is
+ # created again and not restored from sstate.
+ bitbake('-c cleansstate %s' % target)
+ bitbake('-c fetch %s' % target)
+ bb_vars = get_bb_vars(['DL_DIR'])
+ self.track_for_cleanup(bb_vars['DL_DIR'])
+ self.assertTrue(glob.glob(os.path.join(bb_vars['DL_DIR'], 'gitshallow_*.tar.gz')),
+ 'Missing shallow tarball in DL_DIR')
+ shutil.rmtree(os.path.join(bb_vars['DL_DIR'], 'git2'))
+ bitbake('-c cleansstate %s' % target)
+
+ bitbake('-c deploy_archives %s' % target)
+
+ names = self._get_original_git_archive_names(target)
+ self.assertTrue([n for n in names if n.endswith('/COPYING')], 'Archive has no source files: %s' % names[:20])
+
+ def _get_original_git_archive_names(self, target):
+ """
+ Return the names of the files in the original source archive of the
+ git source of target.
+ """
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC'], target)
+ archives = glob.glob(os.path.join(bb_vars['DEPLOY_DIR_SRC'], '*', '%s-*' % target, '%s-*.tar.*' % target))
+ self.assertEqual(len(archives), 1, 'Expected one source archive for %s, found %s' % (target, archives))
+ with tarfile.open(archives[0]) as tar:
+ return tar.getnames()
+
def test_archiver_mode_patched(self):
"""
Test that the archiver works with `ARCHIVER_MODE[src] = "patched"`.
--
2.43.0
next prev parent reply other threads:[~2026-10-30 17:45 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 17:45 [PATCH v2 0/3] *** archiver.bbclass: archive shallow git sources which have no clone *** ecordonnier
2026-10-30 17:45 ` ecordonnier [this message]
2026-10-30 17:45 ` [PATCH v2 2/3] archiver.bbclass: remove .git from original git source archives ecordonnier
2026-10-30 17:45 ` [PATCH v2 3/3] archiver.bbclass: fail on sources which cannot be archived ecordonnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030174536.2724008-2-ecordonnier@snap.com \
--to=ecordonnier@snap.com \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox