bitbake: fetch2/git: verify if local clone contains tag

In case a recipe specifies a git SRC_URI along with revision and tag, but only the
revision is present in the local clone without the tag (because it was tagged after
it was cloned), then unpacking fails with the following error:

... rev-list -n 1 1.0 failed with exit code 128, output:\nfatal: ambiguous argument \'1.0\': unknown revision or path not in the working tree

This happens because the during the download step only the revision's presence is
verified to decide if the repository needs to be updated.

To avoid this, check also if the tag is present in the local repository, when the "tag"
tag is specified.

(Bitbake rev: 546b347b4d3d82c01ecc99f45296f66e44638adc)

Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Gyorgy Sarvari 2025-08-15 21:44:01 +02:00 committed by Richard Purdie
parent 2f808c92cc
commit 3d451f3452
2 changed files with 51 additions and 3 deletions

View File

@ -323,6 +323,8 @@ class Git(FetchMethod):
return True
if not self._contains_ref(ud, d, ud.name, ud.clonedir):
return True
if 'tag' in ud.parm and not self._contains_ref(ud, d, ud.name, ud.clonedir, tag=True):
return True
return False
def lfs_need_update(self, ud, d):
@ -775,14 +777,16 @@ class Git(FetchMethod):
def supports_srcrev(self):
return True
def _contains_ref(self, ud, d, name, wd):
def _contains_ref(self, ud, d, name, wd, tag=False):
cmd = ""
git_ref_name = 'refs/tags/%s' % ud.parm['tag'] if tag else ud.revision
if ud.nobranch:
cmd = "%s log --pretty=oneline -n 1 %s -- 2> /dev/null | wc -l" % (
ud.basecmd, ud.revision)
ud.basecmd, git_ref_name)
else:
cmd = "%s branch --contains %s --list %s 2> /dev/null | wc -l" % (
ud.basecmd, ud.revision, ud.branch)
ud.basecmd, git_ref_name, ud.branch)
try:
output = runfetchcmd(cmd, d, quiet=True, workdir=wd)
except bb.fetch2.FetchError:

View File

@ -2647,6 +2647,50 @@ class GitURLWithSpacesTest(FetcherTest):
self.assertEqual(ud.fullmirror, os.path.join(self.dldir, "git2_" + ref['gitsrcname'] + '.tar.gz'))
self.assertEqual(ud.method._get_repo_url(ud), ref['repo_url'])
class FetchLocallyMissingTagFromRemote(FetcherTest):
def setUp(self):
FetcherTest.setUp(self)
self.gitdir = os.path.join(self.tempdir, 'git')
self.srcdir = os.path.join(self.tempdir, 'gitsource')
bb.utils.mkdirhier(self.srcdir)
self.git_init(cwd=self.srcdir)
self.d.setVar('WORKDIR', self.tempdir)
self.d.setVar('S', self.gitdir)
uri = 'git://%s;protocol=file;subdir=${S};branch=master' % self.srcdir
self.d.setVar('SRC_URI', uri)
open(os.path.join(self.srcdir, 'dummyfile'), 'w').close()
self.git(['add', 'dummyfile'], self.srcdir)
self.git(['commit', '-m', 'dummymsg', 'dummyfile'], self.srcdir)
def _fetch_and_unpack(self, uri_to_fetch):
fetcher = bb.fetch2.Fetch([uri_to_fetch], self.d)
fetcher.download()
fetcher.unpack(self.d.getVar('WORKDIR'))
def test_tag_present_in_remote_but_not_local(self):
# fetch a repo that has no tag in it
# then add a tag to this repo, and fetch it again, without
# changing SRC_REV, but by adding ';tag=tag1` to SRC_URI
# the new tag should be fetched and unpacked
srcrev = self.git('rev-parse HEAD', cwd=self.srcdir).strip()
self.d.setVar('SRCREV', srcrev)
src_uri = self.d.getVar('SRC_URI')
self._fetch_and_unpack(src_uri)
self.git('tag -m -a tag1', cwd=self.srcdir)
src_uri = '%s;tag=tag1' % self.d.getVar('SRC_URI').split()[0]
self.d.setVar('SRC_URI', src_uri)
self._fetch_and_unpack(src_uri)
output = self.git('log --pretty=oneline -n 1 refs/tags/tag1', cwd=self.gitdir)
assert "fatal: ambiguous argument" not in output
class CrateTest(FetcherTest):
@skipIfNoNetwork()
def test_crate_url(self):