summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorMatt Hoosier <matt.hoosier@garmin.com>2021-02-03 04:22:09 -1000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-02-05 12:18:38 +0000
commit977b7268bf4fd425cb86d4a57500350c9b829162 (patch)
treee1430bb0ce01b6f4a0b1d577e8b579b4135b47d5 /bitbake
parent1f4ca119bef0e06b8ed18f6c7878a3704014ec71 (diff)
downloadpoky-977b7268bf4fd425cb86d4a57500350c9b829162.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: 2351b496bb63b96920d4ae67bec816f00d510df2) 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: Steve Sakoman <steve@sakoman.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 07064c694f..8740e9c05f 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -378,6 +378,35 @@ class Git(FetchMethod):
378 if missing_rev: 378 if missing_rev:
379 raise bb.fetch2.FetchError("Unable to find revision %s even from upstream" % missing_rev) 379 raise bb.fetch2.FetchError("Unable to find revision %s even from upstream" % missing_rev)
380 380
381 if self._contains_lfs(ud, d, ud.clonedir) and self._need_lfs(ud):
382 # Unpack temporary working copy, use it to run 'git checkout' to force pre-fetching
383 # of all LFS blobs needed at the the srcrev.
384 #
385 # It would be nice to just do this inline here by running 'git-lfs fetch'
386 # on the bare clonedir, but that operation requires a working copy on some
387 # releases of Git LFS.
388 tmpdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
389 try:
390 # Do the checkout. This implicitly involves a Git LFS fetch.
391 self.unpack(ud, tmpdir, d)
392
393 # Scoop up a copy of any stuff that Git LFS downloaded. Merge them into
394 # the bare clonedir.
395 #
396 # As this procedure is invoked repeatedly on incremental fetches as
397 # a recipe's SRCREV is bumped throughout its lifetime, this will
398 # result in a gradual accumulation of LFS blobs in <ud.clonedir>/lfs
399 # corresponding to all the blobs reachable from the different revs
400 # fetched across time.
401 #
402 # Only do this if the unpack resulted in a .git/lfs directory being
403 # created; this only happens if at least one blob needed to be
404 # downloaded.
405 if os.path.exists(os.path.join(tmpdir, "git", ".git", "lfs")):
406 runfetchcmd("tar -cf - lfs | tar -xf - -C %s" % ud.clonedir, d, workdir="%s/git/.git" % tmpdir)
407 finally:
408 bb.utils.remove(tmpdir, recurse=True)
409
381 def build_mirror_data(self, ud, d): 410 def build_mirror_data(self, ud, d):
382 if ud.shallow and ud.write_shallow_tarballs: 411 if ud.shallow and ud.write_shallow_tarballs:
383 if not os.path.exists(ud.fullshallow): 412 if not os.path.exists(ud.fullshallow):
@@ -473,7 +502,7 @@ class Git(FetchMethod):
473 if os.path.exists(destdir): 502 if os.path.exists(destdir):
474 bb.utils.prunedir(destdir) 503 bb.utils.prunedir(destdir)
475 504
476 need_lfs = ud.parm.get("lfs", "1") == "1" 505 need_lfs = self._need_lfs(ud)
477 506
478 if not need_lfs: 507 if not need_lfs:
479 ud.basecmd = "GIT_LFS_SKIP_SMUDGE=1 " + ud.basecmd 508 ud.basecmd = "GIT_LFS_SKIP_SMUDGE=1 " + ud.basecmd
@@ -562,6 +591,9 @@ class Git(FetchMethod):
562 raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output)) 591 raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output))
563 return output.split()[0] != "0" 592 return output.split()[0] != "0"
564 593
594 def _need_lfs(self, ud):
595 return ud.parm.get("lfs", "1") == "1"
596
565 def _contains_lfs(self, ud, d, wd): 597 def _contains_lfs(self, ud, d, wd):
566 """ 598 """
567 Check if the repository has 'lfs' (large file) content 599 Check if the repository has 'lfs' (large file) content
@@ -572,8 +604,14 @@ class Git(FetchMethod):
572 else: 604 else:
573 branchname = "master" 605 branchname = "master"
574 606
575 cmd = "%s grep lfs origin/%s:.gitattributes | wc -l" % ( 607 # The bare clonedir doesn't use the remote names; it has the branch immediately.
576 ud.basecmd, ud.branches[ud.names[0]]) 608 if wd == ud.clonedir:
609 refname = ud.branches[ud.names[0]]
610 else:
611 refname = "origin/%s" % ud.branches[ud.names[0]]
612
613 cmd = "%s grep lfs %s:.gitattributes | wc -l" % (
614 ud.basecmd, refname)
577 615
578 try: 616 try:
579 output = runfetchcmd(cmd, d, quiet=True, workdir=wd) 617 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 4702c99a7e..9453c90d2b 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -2046,13 +2046,14 @@ class GitLfsTest(FetcherTest):
2046 cwd = self.gitdir 2046 cwd = self.gitdir
2047 return bb.process.run(cmd, cwd=cwd)[0] 2047 return bb.process.run(cmd, cwd=cwd)[0]
2048 2048
2049 def fetch(self, uri=None): 2049 def fetch(self, uri=None, download=True):
2050 uris = self.d.getVar('SRC_URI').split() 2050 uris = self.d.getVar('SRC_URI').split()
2051 uri = uris[0] 2051 uri = uris[0]
2052 d = self.d 2052 d = self.d
2053 2053
2054 fetcher = bb.fetch2.Fetch(uris, d) 2054 fetcher = bb.fetch2.Fetch(uris, d)
2055 fetcher.download() 2055 if download:
2056 fetcher.download()
2056 ud = fetcher.ud[uri] 2057 ud = fetcher.ud[uri]
2057 return fetcher, ud 2058 return fetcher, ud
2058 2059
@@ -2062,16 +2063,21 @@ class GitLfsTest(FetcherTest):
2062 uri = 'git://%s;protocol=file;subdir=${S};lfs=1' % self.srcdir 2063 uri = 'git://%s;protocol=file;subdir=${S};lfs=1' % self.srcdir
2063 self.d.setVar('SRC_URI', uri) 2064 self.d.setVar('SRC_URI', uri)
2064 2065
2065 fetcher, ud = self.fetch() 2066 # Careful: suppress initial attempt at downloading until
2067 # we know whether git-lfs is installed.
2068 fetcher, ud = self.fetch(uri=None, download=False)
2066 self.assertIsNotNone(ud.method._find_git_lfs) 2069 self.assertIsNotNone(ud.method._find_git_lfs)
2067 2070
2068 # If git-lfs can be found, the unpack should be successful 2071 # If git-lfs can be found, the unpack should be successful. Only
2069 ud.method._find_git_lfs = lambda d: True 2072 # attempt this with the real live copy of git-lfs installed.
2070 shutil.rmtree(self.gitdir, ignore_errors=True) 2073 if ud.method._find_git_lfs(self.d):
2071 fetcher.unpack(self.d.getVar('WORKDIR')) 2074 fetcher.download()
2075 shutil.rmtree(self.gitdir, ignore_errors=True)
2076 fetcher.unpack(self.d.getVar('WORKDIR'))
2072 2077
2073 # If git-lfs cannot be found, the unpack should throw an error 2078 # If git-lfs cannot be found, the unpack should throw an error
2074 with self.assertRaises(bb.fetch2.FetchError): 2079 with self.assertRaises(bb.fetch2.FetchError):
2080 fetcher.download()
2075 ud.method._find_git_lfs = lambda d: False 2081 ud.method._find_git_lfs = lambda d: False
2076 shutil.rmtree(self.gitdir, ignore_errors=True) 2082 shutil.rmtree(self.gitdir, ignore_errors=True)
2077 fetcher.unpack(self.d.getVar('WORKDIR')) 2083 fetcher.unpack(self.d.getVar('WORKDIR'))
@@ -2082,10 +2088,16 @@ class GitLfsTest(FetcherTest):
2082 uri = 'git://%s;protocol=file;subdir=${S};lfs=0' % self.srcdir 2088 uri = 'git://%s;protocol=file;subdir=${S};lfs=0' % self.srcdir
2083 self.d.setVar('SRC_URI', uri) 2089 self.d.setVar('SRC_URI', uri)
2084 2090
2091 # In contrast to test_lfs_enabled(), allow the implicit download
2092 # done by self.fetch() to occur here. The point of this test case
2093 # is to verify that the fetcher can survive even if the source
2094 # repository has Git LFS usage configured.
2085 fetcher, ud = self.fetch() 2095 fetcher, ud = self.fetch()
2086 self.assertIsNotNone(ud.method._find_git_lfs) 2096 self.assertIsNotNone(ud.method._find_git_lfs)
2087 2097
2088 # If git-lfs can be found, the unpack should be successful 2098 # If git-lfs can be found, the unpack should be successful. A
2099 # live copy of git-lfs is not required for this case, so
2100 # unconditionally forge its presence.
2089 ud.method._find_git_lfs = lambda d: True 2101 ud.method._find_git_lfs = lambda d: True
2090 shutil.rmtree(self.gitdir, ignore_errors=True) 2102 shutil.rmtree(self.gitdir, ignore_errors=True)
2091 fetcher.unpack(self.d.getVar('WORKDIR')) 2103 fetcher.unpack(self.d.getVar('WORKDIR'))