summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/fetch2/git.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/fetch2/git.py')
-rw-r--r--bitbake/lib/bb/fetch2/git.py114
1 files changed, 85 insertions, 29 deletions
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index 168f14d0c8..9a15abaa79 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -207,6 +207,7 @@ class Git(FetchMethod):
207 if ud.bareclone: 207 if ud.bareclone:
208 ud.cloneflags += " --mirror" 208 ud.cloneflags += " --mirror"
209 209
210 ud.shallow_skip_fast = False
210 ud.shallow = d.getVar("BB_GIT_SHALLOW") == "1" 211 ud.shallow = d.getVar("BB_GIT_SHALLOW") == "1"
211 ud.shallow_extra_refs = (d.getVar("BB_GIT_SHALLOW_EXTRA_REFS") or "").split() 212 ud.shallow_extra_refs = (d.getVar("BB_GIT_SHALLOW_EXTRA_REFS") or "").split()
212 213
@@ -446,6 +447,24 @@ class Git(FetchMethod):
446 if ud.proto.lower() != 'file': 447 if ud.proto.lower() != 'file':
447 bb.fetch2.check_network_access(d, clone_cmd, ud.url) 448 bb.fetch2.check_network_access(d, clone_cmd, ud.url)
448 progresshandler = GitProgressHandler(d) 449 progresshandler = GitProgressHandler(d)
450
451 # Try creating a fast initial shallow clone
452 # Enabling ud.shallow_skip_fast will skip this
453 # If the Git error "Server does not allow request for unadvertised object"
454 # occurs, shallow_skip_fast is enabled automatically.
455 # This may happen if the Git server does not allow the request
456 # or if the Git client has issues with this functionality.
457 if ud.shallow and not ud.shallow_skip_fast:
458 try:
459 self.clone_shallow_with_tarball(ud, d)
460 # When the shallow clone has succeeded, use the shallow tarball
461 ud.localpath = ud.fullshallow
462 return
463 except:
464 logger.warning("Creating fast initial shallow clone failed, try initial regular clone now.")
465
466 # When skipping fast initial shallow or the fast inital shallow clone failed:
467 # Try again with an initial regular clone
449 runfetchcmd(clone_cmd, d, log=progresshandler) 468 runfetchcmd(clone_cmd, d, log=progresshandler)
450 469
451 # Update the checkout if needed 470 # Update the checkout if needed
@@ -508,48 +527,74 @@ class Git(FetchMethod):
508 if os.path.exists(os.path.join(ud.destdir, ".git", "lfs")): 527 if os.path.exists(os.path.join(ud.destdir, ".git", "lfs")):
509 runfetchcmd("tar -cf - lfs | tar -xf - -C %s" % ud.clonedir, d, workdir="%s/.git" % ud.destdir) 528 runfetchcmd("tar -cf - lfs | tar -xf - -C %s" % ud.clonedir, d, workdir="%s/.git" % ud.destdir)
510 529
511 def build_mirror_data(self, ud, d): 530 def lfs_fetch(self, ud, d, clonedir, revision, fetchall=False, progresshandler=None):
512 531 """Helper method for fetching Git LFS data"""
513 # Create as a temp file and move atomically into position to avoid races 532 try:
514 @contextmanager 533 if self._need_lfs(ud) and self._contains_lfs(ud, d, clonedir) and self._find_git_lfs(d) and len(revision):
515 def create_atomic(filename): 534 # Using worktree with the revision because .lfsconfig may exists
516 fd, tfile = tempfile.mkstemp(dir=os.path.dirname(filename)) 535 worktree_add_cmd = "%s worktree add wt %s" % (ud.basecmd, revision)
517 try: 536 runfetchcmd(worktree_add_cmd, d, log=progresshandler, workdir=clonedir)
518 yield tfile 537 lfs_fetch_cmd = "%s lfs fetch %s" % (ud.basecmd, "--all" if fetchall else "")
519 umask = os.umask(0o666) 538 runfetchcmd(lfs_fetch_cmd, d, log=progresshandler, workdir=(clonedir + "/wt"))
520 os.umask(umask) 539 worktree_rem_cmd = "%s worktree remove -f wt" % ud.basecmd
521 os.chmod(tfile, (0o666 & ~umask)) 540 runfetchcmd(worktree_rem_cmd, d, log=progresshandler, workdir=clonedir)
522 os.rename(tfile, filename) 541 except:
523 finally: 542 logger.warning("Fetching LFS did not succeed.")
524 os.close(fd) 543
544 @contextmanager
545 def create_atomic(self, filename):
546 """Create as a temp file and move atomically into position to avoid races"""
547 fd, tfile = tempfile.mkstemp(dir=os.path.dirname(filename))
548 try:
549 yield tfile
550 umask = os.umask(0o666)
551 os.umask(umask)
552 os.chmod(tfile, (0o666 & ~umask))
553 os.rename(tfile, filename)
554 finally:
555 os.close(fd)
525 556
557 def build_mirror_data(self, ud, d):
526 if ud.shallow and ud.write_shallow_tarballs: 558 if ud.shallow and ud.write_shallow_tarballs:
527 if not os.path.exists(ud.fullshallow): 559 if not os.path.exists(ud.fullshallow):
528 if os.path.islink(ud.fullshallow): 560 if os.path.islink(ud.fullshallow):
529 os.unlink(ud.fullshallow) 561 os.unlink(ud.fullshallow)
530 tempdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR')) 562 self.clone_shallow_with_tarball(ud, d)
531 shallowclone = os.path.join(tempdir, 'git')
532 try:
533 self.clone_shallow_local(ud, shallowclone, d)
534
535 logger.info("Creating tarball of git repository")
536 with create_atomic(ud.fullshallow) as tfile:
537 runfetchcmd("tar -czf %s ." % tfile, d, workdir=shallowclone)
538 runfetchcmd("touch %s.done" % ud.fullshallow, d)
539 finally:
540 bb.utils.remove(tempdir, recurse=True)
541 elif ud.write_tarballs and not os.path.exists(ud.fullmirror): 563 elif ud.write_tarballs and not os.path.exists(ud.fullmirror):
542 if os.path.islink(ud.fullmirror): 564 if os.path.islink(ud.fullmirror):
543 os.unlink(ud.fullmirror) 565 os.unlink(ud.fullmirror)
544 566
545 logger.info("Creating tarball of git repository") 567 logger.info("Creating tarball of git repository")
546 with create_atomic(ud.fullmirror) as tfile: 568 with self.create_atomic(ud.fullmirror) as tfile:
547 mtime = runfetchcmd("{} log --all -1 --format=%cD".format(ud.basecmd), d, 569 mtime = runfetchcmd("{} log --all -1 --format=%cD".format(ud.basecmd), d,
548 quiet=True, workdir=ud.clonedir) 570 quiet=True, workdir=ud.clonedir)
549 runfetchcmd("tar -czf %s --owner oe:0 --group oe:0 --mtime \"%s\" ." 571 runfetchcmd("tar -czf %s --owner oe:0 --group oe:0 --mtime \"%s\" ."
550 % (tfile, mtime), d, workdir=ud.clonedir) 572 % (tfile, mtime), d, workdir=ud.clonedir)
551 runfetchcmd("touch %s.done" % ud.fullmirror, d) 573 runfetchcmd("touch %s.done" % ud.fullmirror, d)
552 574
575 def clone_shallow_with_tarball(self, ud, d):
576 ret = False
577 tempdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
578 shallowclone = os.path.join(tempdir, 'git')
579 try:
580 try:
581 self.clone_shallow_local(ud, shallowclone, d)
582 except:
583 logger.warning("Fash shallow clone failed, try to skip fast mode now.")
584 bb.utils.remove(tempdir, recurse=True)
585 os.mkdir(tempdir)
586 ud.shallow_skip_fast = True
587 self.clone_shallow_local(ud, shallowclone, d)
588 logger.info("Creating tarball of git repository")
589 with self.create_atomic(ud.fullshallow) as tfile:
590 runfetchcmd("tar -czf %s ." % tfile, d, workdir=shallowclone)
591 runfetchcmd("touch %s.done" % ud.fullshallow, d)
592 ret = True
593 finally:
594 bb.utils.remove(tempdir, recurse=True)
595
596 return ret
597
553 def clone_shallow_local(self, ud, dest, d): 598 def clone_shallow_local(self, ud, dest, d):
554 """ 599 """
555 Shallow fetch from ud.clonedir (${DL_DIR}/git2/<gitrepo> by default): 600 Shallow fetch from ud.clonedir (${DL_DIR}/git2/<gitrepo> by default):
@@ -557,12 +602,20 @@ class Git(FetchMethod):
557 - For BB_GIT_SHALLOW_REVS: git fetch --shallow-exclude=<revs> rev 602 - For BB_GIT_SHALLOW_REVS: git fetch --shallow-exclude=<revs> rev
558 """ 603 """
559 604
605 progresshandler = GitProgressHandler(d)
606 repourl = self._get_repo_url(ud)
560 bb.utils.mkdirhier(dest) 607 bb.utils.mkdirhier(dest)
561 init_cmd = "%s init -q" % ud.basecmd 608 init_cmd = "%s init -q" % ud.basecmd
562 if ud.bareclone: 609 if ud.bareclone:
563 init_cmd += " --bare" 610 init_cmd += " --bare"
564 runfetchcmd(init_cmd, d, workdir=dest) 611 runfetchcmd(init_cmd, d, workdir=dest)
565 runfetchcmd("%s remote add origin %s" % (ud.basecmd, ud.clonedir), d, workdir=dest) 612 # Use repourl when creating a fast initial shallow clone
613 # Prefer already existing full bare clones if available
614 if not ud.shallow_skip_fast and not os.path.exists(ud.clonedir):
615 remote = shlex.quote(repourl)
616 else:
617 remote = ud.clonedir
618 runfetchcmd("%s remote add origin %s" % (ud.basecmd, remote), d, workdir=dest)
566 619
567 # Check the histories which should be excluded 620 # Check the histories which should be excluded
568 shallow_exclude = '' 621 shallow_exclude = ''
@@ -600,10 +653,14 @@ class Git(FetchMethod):
600 # The ud.clonedir is a local temporary dir, will be removed when 653 # The ud.clonedir is a local temporary dir, will be removed when
601 # fetch is done, so we can do anything on it. 654 # fetch is done, so we can do anything on it.
602 adv_cmd = 'git branch -f advertise-%s %s' % (revision, revision) 655 adv_cmd = 'git branch -f advertise-%s %s' % (revision, revision)
603 runfetchcmd(adv_cmd, d, workdir=ud.clonedir) 656 if ud.shallow_skip_fast:
657 runfetchcmd(adv_cmd, d, workdir=ud.clonedir)
604 658
605 runfetchcmd(fetch_cmd, d, workdir=dest) 659 runfetchcmd(fetch_cmd, d, workdir=dest)
606 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest) 660 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest)
661 # Fetch Git LFS data for fast shallow clones
662 if not ud.shallow_skip_fast:
663 self.lfs_fetch(ud, d, dest, ud.revisions[ud.names[0]])
607 664
608 # Apply extra ref wildcards 665 # Apply extra ref wildcards
609 all_refs_remote = runfetchcmd("%s ls-remote origin 'refs/*'" % ud.basecmd, \ 666 all_refs_remote = runfetchcmd("%s ls-remote origin 'refs/*'" % ud.basecmd, \
@@ -629,7 +686,6 @@ class Git(FetchMethod):
629 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest) 686 runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest)
630 687
631 # The url is local ud.clonedir, set it to upstream one 688 # 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) 689 runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=dest)
634 690
635 def unpack(self, ud, destdir, d): 691 def unpack(self, ud, destdir, d):