summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorRobert Yang <liezhi.yang@windriver.com>2024-07-07 00:20:37 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-07-13 23:30:07 +0100
commite2527cf58f4f390712641a99b276b9e0aeae01c6 (patch)
tree042f0172ed1f34b3800d479dce8cfa00c0426407 /bitbake
parentae4ec59b3eff85aaa1cfe914a134e56e1d125744 (diff)
downloadpoky-e2527cf58f4f390712641a99b276b9e0aeae01c6.tar.gz
bitbake: fetch2/git: Use git shallow fetch to implement clone_shallow_local()
This patch can make the following settings much more faster: BB_GIT_SHALLOW = "1" BB_GENERATE_MIRROR_TARBALLS = "1" * The previous implementation was: - Make a full clone for the repo from local ud.clonedir - Use git-make-shallow to remove unneeded revs It was very slow for recipes which have a lot of SRC_URIs, for example vulkan-samples and docker-compose, the docker-compose can't be done after 5 hours. $ bitbake vulkan-samples -cfetch Before: 12 minutes Now: 2 minutes $ bitbake docker-compose -cfetch Before: More than 300 minutes Now: 15 minutes * The patch uses git shallow fetch to fetch the repo from local ud.clonedir: - For BB_GIT_SHALLOW_DEPTH: git fetch --depth <depth> rev - For BB_GIT_SHALLOW_REVS: git fetch --shallow-exclude=<revs> rev Then the git repo will be shallow, and git-make-shallow is not needed any more. And git shallow fetch will download less commits than before since it doesn't need "rev^" to parse the dependencies, the previous code always need 'rev^'. (Bitbake rev: a5a569c075224fe41707cfa9123c442d1fda2fbf) Signed-off-by: Robert Yang <liezhi.yang@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/fetch2/git.py78
1 files changed, 52 insertions, 26 deletions
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index c7ff769fdf..16bc1f1cf8 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -551,18 +551,31 @@ class Git(FetchMethod):
551 runfetchcmd("touch %s.done" % ud.fullmirror, d) 551 runfetchcmd("touch %s.done" % ud.fullmirror, d)
552 552
553 def clone_shallow_local(self, ud, dest, d): 553 def clone_shallow_local(self, ud, dest, d):
554 """Clone the repo and make it shallow. 554 """
555 Shallow fetch from ud.clonedir (${DL_DIR}/git2/<gitrepo> by default):
556 - For BB_GIT_SHALLOW_DEPTH: git fetch --depth <depth> rev
557 - For BB_GIT_SHALLOW_REVS: git fetch --shallow-exclude=<revs> rev
558 """
559
560 bb.utils.mkdirhier(dest)
561 init_cmd = "%s init -q" % ud.basecmd
562 if ud.bareclone:
563 init_cmd += " --bare"
564 runfetchcmd(init_cmd, d, workdir=dest)
565 runfetchcmd("%s remote add origin %s" % (ud.basecmd, ud.clonedir), d, workdir=dest)
555 566
556 The upstream url of the new clone isn't set at this time, as it'll be 567 # Check the histories which should be excluded
557 set correctly when unpacked.""" 568 shallow_exclude = ''
558 runfetchcmd("%s clone %s %s %s" % (ud.basecmd, ud.cloneflags, ud.clonedir, dest), d) 569 for revision in ud.shallow_revs:
570 shallow_exclude += " --shallow-exclude=%s" % revision
559 571
560 to_parse, shallow_branches = [], []
561 for name in ud.names: 572 for name in ud.names:
562 revision = ud.revisions[name] 573 revision = ud.revisions[name]
563 depth = ud.shallow_depths[name] 574 depth = ud.shallow_depths[name]
564 if depth: 575
565 to_parse.append('%s~%d^{}' % (revision, depth - 1)) 576 # The --depth and --shallow-exclude can't be used together
577 if depth and shallow_exclude:
578 raise bb.fetch2.FetchError("BB_GIT_SHALLOW_REVS is set, but BB_GIT_SHALLOW_DEPTH is not 0.")
566 579
567 # For nobranch, we need a ref, otherwise the commits will be 580 # For nobranch, we need a ref, otherwise the commits will be
568 # removed, and for non-nobranch, we truncate the branch to our 581 # removed, and for non-nobranch, we truncate the branch to our
@@ -575,36 +588,49 @@ class Git(FetchMethod):
575 else: 588 else:
576 ref = "refs/remotes/origin/%s" % branch 589 ref = "refs/remotes/origin/%s" % branch
577 590
578 shallow_branches.append(ref) 591 fetch_cmd = "%s fetch origin %s" % (ud.basecmd, revision)
579 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest) 592 if depth:
593 fetch_cmd += " --depth %s" % depth
594
595 if shallow_exclude:
596 fetch_cmd += shallow_exclude
580 597
581 # Map srcrev+depths to revisions 598 # Advertise the revision for lower version git such as 2.25.1:
582 parsed_depths = runfetchcmd("%s rev-parse %s" % (ud.basecmd, " ".join(to_parse)), d, workdir=dest) 599 # error: Server does not allow request for unadvertised object.
600 # The ud.clonedir is a local temporary dir, will be removed when
601 # fetch is done, so we can do anything on it.
602 adv_cmd = 'git branch -f advertise-%s %s' % (revision, revision)
603 runfetchcmd(adv_cmd, d, workdir=ud.clonedir)
583 604
584 # Resolve specified revisions 605 runfetchcmd(fetch_cmd, d, workdir=dest)
585 parsed_revs = runfetchcmd("%s rev-parse %s" % (ud.basecmd, " ".join('"%s^{}"' % r for r in ud.shallow_revs)), d, workdir=dest) 606 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest)
586 shallow_revisions = parsed_depths.splitlines() + parsed_revs.splitlines()
587 607
588 # Apply extra ref wildcards 608 # Apply extra ref wildcards
589 all_refs = runfetchcmd('%s for-each-ref "--format=%%(refname)"' % ud.basecmd, 609 all_refs_remote = runfetchcmd("%s ls-remote origin 'refs/*'" % ud.basecmd, \
590 d, workdir=dest).splitlines() 610 d, workdir=dest).splitlines()
611 all_refs = []
612 for line in all_refs_remote:
613 all_refs.append(line.split()[-1])
614 extra_refs = []
591 for r in ud.shallow_extra_refs: 615 for r in ud.shallow_extra_refs:
592 if not ud.bareclone: 616 if not ud.bareclone:
593 r = r.replace('refs/heads/', 'refs/remotes/origin/') 617 r = r.replace('refs/heads/', 'refs/remotes/origin/')
594 618
595 if '*' in r: 619 if '*' in r:
596 matches = filter(lambda a: fnmatch.fnmatchcase(a, r), all_refs) 620 matches = filter(lambda a: fnmatch.fnmatchcase(a, r), all_refs)
597 shallow_branches.extend(matches) 621 extra_refs.extend(matches)
598 else: 622 else:
599 shallow_branches.append(r) 623 extra_refs.append(r)
600 624
601 # Make the repository shallow 625 for ref in extra_refs:
602 shallow_cmd = [self.make_shallow_path, '-s'] 626 ref_fetch = os.path.basename(ref)
603 for b in shallow_branches: 627 runfetchcmd("%s fetch origin --depth 1 %s" % (ud.basecmd, ref_fetch), d, workdir=dest)
604 shallow_cmd.append('-r') 628 revision = runfetchcmd("%s rev-parse FETCH_HEAD" % ud.basecmd, d, workdir=dest)
605 shallow_cmd.append(b) 629 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest)
606 shallow_cmd.extend(shallow_revisions) 630
607 runfetchcmd(subprocess.list2cmdline(shallow_cmd), d, workdir=dest) 631 # The url is local ud.clonedir, set it to upstream one
632 repourl = self._get_repo_url(ud)
633 runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=dest)
608 634
609 def unpack(self, ud, destdir, d): 635 def unpack(self, ud, destdir, d):
610 """ unpack the downloaded src to destdir""" 636 """ unpack the downloaded src to destdir"""