summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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'))