All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "openembedded-core@lists.openembedded.org"
	<openembedded-core@lists.openembedded.org>,
	"alex.kanavin@gmail.com" <alex.kanavin@gmail.com>,
	"paul@pbarker.dev" <paul@pbarker.dev>
Cc: Troy Lee <troy_lee@aspeedtech.com>, Jamin Lin <jamin_lin@aspeedtech.com>
Subject: [PATCH v3 3/5] devtool-source: Convert nested git SRC_URI destsuffix repos to standalone clones
Date: Thu, 23 Jul 2026 08:11:23 +0000	[thread overview]
Message-ID: <20260723081118.1558249-4-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20260723081118.1558249-1-jamin_lin@aspeedtech.com>

When a recipe uses multiple git SRC_URI entries with different destsuffix
values (e.g. recipes with separate repositories for the kernel, modules
and application), do_unpack clones each source tree with
'git clone -n -s'.

The -s flag uses git's shared-object mechanism:
instead of copying objects locally it writes a .git/objects/info/alternates file
pointing back to the bare repository under the downloads directory (DL_DIR/git2/).

scriptutils.git_convert_standalone_clone() is called by devtool_post_unpack to
make the top-level source directory standalone: it runs 'git repack -a' to copy
all objects into the local object store and then removes the alternates file.

However it only processes the top-level source directory. Each nested git repo
created by a separate SRC_URI entry retains its own alternates file still
pointing into downloads/.

Steps to reproduce:
  1. devtool modify <recipe-with-multiple-git-SRC_URI>
  2. bitbake -c cleanall <recipe>
  3. bitbake <recipe>

At step 2, 'bitbake -c cleanall' calls fetcher.clean() which deletes
the bare repositories from downloads/git2/. The top-level workspace
repo is standalone (alternates already removed by the original code),
but the nested repos still hold alternates pointing to the now-deleted
paths.

At step 3, srctree_hash_files() runs 'git add -A .' with a custom
GIT_INDEX_FILE. Git internally calls 'git status --porcelain=2' on
each nested repo to check for changes; this fails with exit 128 because
the nested alternates are broken:
  error: unable to normalize alternate object path:
         .../downloads/git2/github.com.example.module//objects
  fatal: bad object HEAD
  fatal: 'git status --porcelain=2' failed in submodule modules/lib/module

This halts the BitBake parse phase with a CalledProcessError and leaves
the workspace in an unrecoverable state without manual intervention.

Fix by having devtool_post_unpack() look at the recipe's SRC_URI directly:
any git entry with an explicit destsuffix param names an additional
checkout nested under the source tree, so convert each of those to a
standalone clone the same way as the top-level tree.

This is deliberately metadata-driven rather than walking the unpacked
source tree looking for '.git' directories: a directory walk has no way
to tell a nested checkout from an ordinary subdirectory of one, so it
either has to stop at the first git repo it finds - which then misses a
destsuffix repo nested inside another repo's own working tree - or keep
walking into every repo's contents, which is wasted work for large trees.
Reading SRC_URI instead gives the exact, authoritative set of paths that
need converting, regardless of how they happen to be nested on disk.

Only entries with an explicit destsuffix are handled, since that is the
only way a recipe ends up with more than one git checkout under S; this
also avoids having to duplicate the git fetcher's internal logic for
computing an implicit default destsuffix (which depends on the subdir/
subpath params and BB_GIT_DEFAULT_DESTSUFFIX).

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 meta/classes/devtool-source.bbclass | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/meta/classes/devtool-source.bbclass b/meta/classes/devtool-source.bbclass
index f29f40588f..940cdedbac 100644
--- a/meta/classes/devtool-source.bbclass
+++ b/meta/classes/devtool-source.bbclass
@@ -97,6 +97,22 @@ python devtool_post_unpack() {
 
     scriptutils.git_convert_standalone_clone(srcsubdir)
 
+    # Recipes can use multiple git SRC_URI entries with an explicit destsuffix to
+    # unpack several repositories as nested subdirectories of the source tree
+    # (e.g. recipes with separate repos for the kernel, modules and
+    # application). Each such entry is unpacked as its own 'git clone -s' and
+    # needs the same standalone conversion as srcsubdir above, otherwise it keeps
+    # referencing objects in the downloads dir that 'bitbake -c cleanall' removes.
+    # We only look at entries with an explicit destsuffix param, since that's the
+    # only way a recipe ends up with more than one git checkout under S - this
+    # avoids having to duplicate the fetcher's internal default-destsuffix logic.
+    import bb.fetch2
+    fetch = bb.fetch2.Fetch(d.getVar('SRC_URI').split(), d)
+    for url in fetch.urls:
+        ud = fetch.ud[url]
+        if ud.type == 'git' and ud.parm.get('destsuffix'):
+            scriptutils.git_convert_standalone_clone(os.path.join(unpackdir, ud.parm['destsuffix']))
+
     # Make sure that srcsubdir exists
     bb.utils.mkdirhier(srcsubdir)
     if not os.listdir(srcsubdir):
-- 
2.43.0


  parent reply	other threads:[~2026-07-23  8:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23  8:11 [PATCH v3 0/5] devtool: fix standalone clone conversion for nested git repos Jamin Lin
2026-07-23  8:11 ` [PATCH v3 1/5] devtool: Detect nested git repos before the initial workspace commit Jamin Lin
2026-07-23  8:11 ` [PATCH v3 2/5] oe/patch: Skip commitIgnored when nothing is actually staged Jamin Lin
2026-07-23  8:11 ` Jamin Lin [this message]
2026-07-23  8:11 ` [PATCH v3 4/5] meta-selftest: Add devtool-test-multi-destsuffix recipe Jamin Lin
2026-07-23  8:11 ` [PATCH v3 5/5] oeqa/selftest/devtool: Add test for multiple nested git destsuffix repos Jamin Lin

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=20260723081118.1558249-4-jamin_lin@aspeedtech.com \
    --to=jamin_lin@aspeedtech.com \
    --cc=alex.kanavin@gmail.com \
    --cc=openembedded-core@lists.openembedded.org \
    --cc=paul@pbarker.dev \
    --cc=troy_lee@aspeedtech.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.