summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorMatt Hoosier <matt.hoosier@garmin.com>2021-02-02 13:38:19 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-02-02 15:51:56 +0000
commit95057b9cde43445b5b96fc50b62d30416f0c41e8 (patch)
treeba2f31bec0ee703cd0d56b2e0fcb29c8cf0224d8 /bitbake
parent9de9e2e3194525c8eea57ebc3c7396b4695549a7 (diff)
downloadpoky-95057b9cde43445b5b96fc50b62d30416f0c41e8.tar.gz
bitbake: fetch/git: download LFS content too during do_fetch
Insert an explicit pass to fetch all blobs needed by Git LFS, during the fetch() function. This avoids the default behavior of Git LFS to wait until 'git checkout' to begin downloading the blobs pointed to by LFS records. Network access is not allowed at that point in the recipe's lifecycle. [YOCTO #14191] (Bitbake rev: c73f8f2f4a6491c6bea54839630af6994c27ad24) Signed-off-by: Matt Hoosier <matt.hoosier@garmin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit 0efac66043662e7a2027192f50e92e982db2ba1c) Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/fetch2/git.py44
-rw-r--r--bitbake/lib/bb/tests/fetch.py28
2 files changed, 61 insertions, 11 deletions
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index b97967b487..b59a7cdc84 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -379,6 +379,35 @@ class Git(FetchMethod):
379 if missing_rev: 379 if missing_rev:
380 raise bb.fetch2.FetchError("Unable to find revision %s even from upstream" % missing_rev) 380 raise bb.fetch2.FetchError("Unable to find revision %s even from upstream" % missing_rev)
381 381
382 if self._contains_lfs(ud, d, ud.clonedir) and self._need_lfs(ud):
383 # Unpack temporary working copy, use it to run 'git checkout' to force pre-fetching
384 # of all LFS blobs needed at the the srcrev.
385 #
386 # It would be nice to just do this inline here by running 'git-lfs fetch'
387 # on the bare clonedir, but that operation requires a working copy on some
388 # releases of Git LFS.
389 tmpdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
390 try:
391 # Do the checkout. This implicitly involves a Git LFS fetch.
392 self.unpack(ud, tmpdir, d)
393
394 # Scoop up a copy of any stuff that Git LFS downloaded. Merge them into
395 # the bare clonedir.
396 #
397 # As this procedure is invoked repeatedly on incremental fetches as
398 # a recipe's SRCREV is bumped throughout its lifetime, this will
399 # result in a gradual accumulation of LFS blobs in <ud.clonedir>/lfs
400 # corresponding to all the blobs reachable from the different revs
401 # fetched across time.
402 #
403 # Only do this if the unpack resulted in a .git/lfs directory being
404 # created; this only happens if at least one blob needed to be
405 # downloaded.
406 if os.path.exists(os.path.join(tmpdir, "git", ".git", "lfs")):
407 runfetchcmd("tar -cf - lfs | tar -xf - -C %s" % ud.clonedir, d, workdir="%s/git/.git" % tmpdir)
408 finally:
409 bb.utils.remove(tmpdir, recurse=True)
410
382 def build_mirror_data(self, ud, d): 411 def build_mirror_data(self, ud, d):
383 if ud.shallow and ud.write_shallow_tarballs: 412 if ud.shallow and ud.write_shallow_tarballs:
384 if not os.path.exists(ud.fullshallow): 413 if not os.path.exists(ud.fullshallow):
@@ -474,7 +503,7 @@ class Git(FetchMethod):
474 if os.path.exists(destdir): 503 if os.path.exists(destdir):
475 bb.utils.prunedir(destdir) 504 bb.utils.prunedir(destdir)
476 505
477 need_lfs = ud.parm.get("lfs", "1") == "1" 506 need_lfs = self._need_lfs(ud)
478 507
479 if not need_lfs: 508 if not need_lfs:
480 ud.basecmd = "GIT_LFS_SKIP_SMUDGE=1 " + ud.basecmd 509 ud.basecmd = "GIT_LFS_SKIP_SMUDGE=1 " + ud.basecmd
@@ -563,6 +592,9 @@ class Git(FetchMethod):
563 raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output)) 592 raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output))
564 return output.split()[0] != "0" 593 return output.split()[0] != "0"
565 594
595 def _need_lfs(self, ud):
596 return ud.parm.get("lfs", "1") == "1"
597
566 def _contains_lfs(self, ud, d, wd): 598 def _contains_lfs(self, ud, d, wd):
567 """ 599 """
568 Check if the repository has 'lfs' (large file) content 600 Check if the repository has 'lfs' (large file) content
@@ -573,8 +605,14 @@ class Git(FetchMethod):
573 else: 605 else:
574 branchname = "master" 606 branchname = "master"
575 607
576 cmd = "%s grep lfs origin/%s:.gitattributes | wc -l" % ( 608 # The bare clonedir doesn't use the remote names; it has the branch immediately.
577 ud.basecmd, ud.branches[ud.names[0]]) 609 if wd == ud.clonedir:
610 refname = ud.branches[ud.names[0]]
611 else:
612 refname = "origin/%s" % ud.branches[ud.names[0]]
613
614 cmd = "%s grep lfs %s:.gitattributes | wc -l" % (
615 ud.basecmd, refname)
578 616
579 try: 617 try:
580 output = runfetchcmd(cmd, d, quiet=True, workdir=wd) 618 output = runfetchcmd(cmd, d, quiet=True, workdir=wd)
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py
index da17d7f281..5b70ee810f 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -2051,13 +2051,14 @@ class GitLfsTest(FetcherTest):
2051 cwd = self.gitdir 2051 cwd = self.gitdir
2052 return bb.process.run(cmd, cwd=cwd)[0] 2052 return bb.process.run(cmd, cwd=cwd)[0]
2053 2053
2054 def fetch(self, uri=None): 2054 def fetch(self, uri=None, download=True):
2055 uris = self.d.getVar('SRC_URI').split() 2055 uris = self.d.getVar('SRC_URI').split()
2056 uri = uris[0] 2056 uri = uris[0]
2057 d = self.d 2057 d = self.d
2058 2058
2059 fetcher = bb.fetch2.Fetch(uris, d) 2059 fetcher = bb.fetch2.Fetch(uris, d)
2060 fetcher.download() 2060 if download:
2061 fetcher.download()
2061 ud = fetcher.ud[uri] 2062 ud = fetcher.ud[uri]
2062 return fetcher, ud 2063 return fetcher, ud
2063 2064
@@ -2067,16 +2068,21 @@ class GitLfsTest(FetcherTest):
2067 uri = 'git://%s;protocol=file;subdir=${S};lfs=1' % self.srcdir 2068 uri = 'git://%s;protocol=file;subdir=${S};lfs=1' % self.srcdir
2068 self.d.setVar('SRC_URI', uri) 2069 self.d.setVar('SRC_URI', uri)
2069 2070
2070 fetcher, ud = self.fetch() 2071 # Careful: suppress initial attempt at downloading until
2072 # we know whether git-lfs is installed.
2073 fetcher, ud = self.fetch(uri=None, download=False)
2071 self.assertIsNotNone(ud.method._find_git_lfs) 2074 self.assertIsNotNone(ud.method._find_git_lfs)
2072 2075
2073 # If git-lfs can be found, the unpack should be successful 2076 # If git-lfs can be found, the unpack should be successful. Only
2074 ud.method._find_git_lfs = lambda d: True 2077 # attempt this with the real live copy of git-lfs installed.
2075 shutil.rmtree(self.gitdir, ignore_errors=True) 2078 if ud.method._find_git_lfs(self.d):
2076 fetcher.unpack(self.d.getVar('WORKDIR')) 2079 fetcher.download()
2080 shutil.rmtree(self.gitdir, ignore_errors=True)
2081 fetcher.unpack(self.d.getVar('WORKDIR'))
2077 2082
2078 # If git-lfs cannot be found, the unpack should throw an error 2083 # If git-lfs cannot be found, the unpack should throw an error
2079 with self.assertRaises(bb.fetch2.FetchError): 2084 with self.assertRaises(bb.fetch2.FetchError):
2085 fetcher.download()
2080 ud.method._find_git_lfs = lambda d: False 2086 ud.method._find_git_lfs = lambda d: False
2081 shutil.rmtree(self.gitdir, ignore_errors=True) 2087 shutil.rmtree(self.gitdir, ignore_errors=True)
2082 fetcher.unpack(self.d.getVar('WORKDIR')) 2088 fetcher.unpack(self.d.getVar('WORKDIR'))
@@ -2087,10 +2093,16 @@ class GitLfsTest(FetcherTest):
2087 uri = 'git://%s;protocol=file;subdir=${S};lfs=0' % self.srcdir 2093 uri = 'git://%s;protocol=file;subdir=${S};lfs=0' % self.srcdir
2088 self.d.setVar('SRC_URI', uri) 2094 self.d.setVar('SRC_URI', uri)
2089 2095
2096 # In contrast to test_lfs_enabled(), allow the implicit download
2097 # done by self.fetch() to occur here. The point of this test case
2098 # is to verify that the fetcher can survive even if the source
2099 # repository has Git LFS usage configured.
2090 fetcher, ud = self.fetch() 2100 fetcher, ud = self.fetch()
2091 self.assertIsNotNone(ud.method._find_git_lfs) 2101 self.assertIsNotNone(ud.method._find_git_lfs)
2092 2102
2093 # If git-lfs can be found, the unpack should be successful 2103 # If git-lfs can be found, the unpack should be successful. A
2104 # live copy of git-lfs is not required for this case, so
2105 # unconditionally forge its presence.
2094 ud.method._find_git_lfs = lambda d: True 2106 ud.method._find_git_lfs = lambda d: True
2095 shutil.rmtree(self.gitdir, ignore_errors=True) 2107 shutil.rmtree(self.gitdir, ignore_errors=True)
2096 fetcher.unpack(self.d.getVar('WORKDIR')) 2108 fetcher.unpack(self.d.getVar('WORKDIR'))