Hi Paul

> Hi Paul,
> 
> Thanks for identifying the root cause.
> 
> After studying the devtool design, I now understand what happens: when
> devtool modify creates the workspace, it does not copy the full git object 
> store
> locally.
> Instead, it clones the source tree using git's alternate object store 
> mechanism -
> the workspace's .git/objects/info/alternates file points back to the 
> downloaded
> bare repositories under the downloads/ directory.
> This way the workspace shares the git objects with the download cache rather
> than duplicating them on disk.
> 
> When bitbake -c cleanall is run, it deletes the downloaded bare repositories
> from downloads/. The workspace source tree still exists, but its alternates 
> now
> point to missing paths.
> Any git operation on the workspace (including git status, git add, etc.) then
> fails because git cannot resolve the object references, producing errors like:
> 
> error: unable to normalize alternate object path: 
> .../downloads/git2/.../objects
> fatal: bad object HEAD
> 
> This is what causes the parser to halt with exit 128.
> 
> The fix on my side is straightforward: replace bitbake -c cleanall with 
> bitbake
> -c cleansstate in my devtool workflow. cleansstate clears the sstate cache
> without touching the downloads directory, so the workspace alternates remain
> intact.
> 
> That said, I am not sure whether some improvement on the OE side would still
> be worthwhile. Currently, when this breakage occurs, the user sees only a
> cryptic CalledProcessError: exit 128 with no indication of what went wrong or
> how to recover.
> The situation is also not obvious: running bitbake -c cleanall on a 
> single-repo
> recipe with a devtool workspace does not trigger this problem, so users
> working with multi-repo recipes (such as Zephyr-based recipes that fetch
> multiple git repositories into separate destsuffix directories) are likely to 
> hit
> this unexpectedly. A clearer error message pointing to the root cause and the
> recovery steps (devtool reset -n followed by devtool modify) might save other
> users from the same confusion.
> 
> Please drop this patch series because it is not a normal test case for 
> devtool.
> 
> Below patch that may help improve the user experience, though I leave it to
> the community to decide whether they are worth reviewing:
> 
> Best regards,
> Jamin
> 
> diff --git a/meta/classes/externalsrc.bbclass
> b/meta/classes/externalsrc.bbclass
> index 902ff2604f..3e6c9d937e 100644
> --- a/meta/classes/externalsrc.bbclass
> +++ b/meta/classes/externalsrc.bbclass
> @@ -227,6 +227,57 @@ def srctree_hash_files(d, srcdir=None):
> 
>      ret = " "
>      if git_dir is not None:
> +        # Find nested git repos created by multiple SRC_URI git entries with
> +        # different destsuffix values, so their alternates can also be 
> checked
> +        # for breakage below.
> +        nested_git_dirs = []
> +        for root, dirs, files in os.walk(s_dir):
> +            if root == s_dir:
> +                continue
> +            if '.git' in dirs or '.git' in files:
> +                nested_git_dirs.append(root)
> +                dirs[:] = []
> +
> +        # Check for broken git alternates in the top-level repo and all
> nested
> +        # repos. This can happen when 'bitbake -c cleanall' deletes the
> +        # downloads directory that the devtool workspace references via
> +        # alternates, causing all subsequent git operations to exit 128 and
> +        # halt the parse phase.  Relative alternate paths are resolved
> against
> +        # the repo's objects directory; double-slash paths (a known devtool
> +        # artefact) are normalised before the existence check.
> +        def has_broken_alternates(dot_git):
> +            obj_dir = os.path.join(dot_git, 'objects')
> +            alt_file = os.path.join(obj_dir, 'info', 'alternates')
> +            if not os.path.exists(alt_file):
> +                return False
> +            with open(alt_file) as f:
> +                for line in f:
> +                    path = line.strip()
> +                    if not path or path.startswith('#'):
> +                        continue
> +                    if not os.path.isabs(path):
> +                        path = os.path.join(obj_dir, path)
> +                    if not os.path.exists(os.path.normpath(path)):
> +                        return True
> +            return False
> +
> +        broken = has_broken_alternates(git_dir)
> +        if not broken:
> +            for nested in nested_git_dirs:
> +                nested_dot_git = os.path.join(nested, '.git')
> +                if os.path.isdir(nested_dot_git) and
> has_broken_alternates(nested_dot_git):
> +                    broken = True
> +                    break
> +
> +        if broken:
> +            bb.warn('%s: devtool workspace has broken git alternates, '
> +                    'likely caused by "bitbake -c cleanall" removing the '
> +                    'downloads directory. '
> +                    'To repair the workspace, run: '
> +                    'devtool reset %s && devtool modify %s'
> +                    % (d.getVar('PN'), d.getVar('PN'), d.getVar('PN')))
> +            return s_dir + '/*:True'
> +
> 


Please ignore the comments above.
I believe I have identified the root cause. Please see my updated solution here:
https://patchwork.yoctoproject.org/project/oe-core/patch/[email protected]/

Thanks,
Jamin
> 
> 
> 

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#237383): 
https://lists.openembedded.org/g/openembedded-core/message/237383
Mute This Topic: https://lists.openembedded.org/mt/119327122/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to