summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorNathan Rossi <nathan@nathanrossi.com>2018-02-02 23:51:15 +1000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2018-02-14 15:26:03 +0000
commitf2d5967982359b924406e3937a8e32807a5bb533 (patch)
treeef149278615cd8683e7893ef5ae0a69f658cf334 /bitbake
parentbb3a634226c68b235d0110b9955d0aae7dde994a (diff)
downloadpoky-f2d5967982359b924406e3937a8e32807a5bb533.tar.gz
bitbake: fetch2: Handle missing donestamp file when content is valid
In order to allow users to manually populate the download directory with valid content change the assumption that missing the donestamp file means unfetched content. This allows users to populate the download dir without needing to create dummy .done files such that a user does not need a PREMIRROR when using BB_NO_NETWORK to provide valid content files in the download directory. To ensure the correct result this change also fails first if the localpath does not exist. This prevents further parts of the function attempting to calculating the checksum on non-existent files. This also fixes some edge conditions around where if the donestamp exists but the localpath does not it returns, and did not remove the donestamp. Also added test cases to cover this use case and additional use cases where for example the fetcher does not support checksums. (Bitbake rev: a335dbbb65d5b56e71d98cf3e4fa9bfbec1dcde6) Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/fetch2/__init__.py21
-rw-r--r--bitbake/lib/bb/tests/fetch.py104
2 files changed, 114 insertions, 11 deletions
diff --git a/bitbake/lib/bb/fetch2/__init__.py b/bitbake/lib/bb/fetch2/__init__.py
index 6bd040493e..72d6092deb 100644
--- a/bitbake/lib/bb/fetch2/__init__.py
+++ b/bitbake/lib/bb/fetch2/__init__.py
@@ -643,26 +643,25 @@ def verify_donestamp(ud, d, origud=None):
643 if not ud.needdonestamp or (origud and not origud.needdonestamp): 643 if not ud.needdonestamp or (origud and not origud.needdonestamp):
644 return True 644 return True
645 645
646 if not os.path.exists(ud.donestamp): 646 if not os.path.exists(ud.localpath):
647 # local path does not exist
648 if os.path.exists(ud.donestamp):
649 # done stamp exists, but the downloaded file does not; the done stamp
650 # must be incorrect, re-trigger the download
651 bb.utils.remove(ud.donestamp)
647 return False 652 return False
648 653
649 if (not ud.method.supports_checksum(ud) or 654 if (not ud.method.supports_checksum(ud) or
650 (origud and not origud.method.supports_checksum(origud))): 655 (origud and not origud.method.supports_checksum(origud))):
651 # done stamp exists, checksums not supported; assume the local file is 656 # if done stamp exists and checksums not supported; assume the local
652 # current 657 # file is current
653 return True 658 return os.path.exists(ud.donestamp)
654
655 if not os.path.exists(ud.localpath):
656 # done stamp exists, but the downloaded file does not; the done stamp
657 # must be incorrect, re-trigger the download
658 bb.utils.remove(ud.donestamp)
659 return False
660 659
661 precomputed_checksums = {} 660 precomputed_checksums = {}
662 # Only re-use the precomputed checksums if the donestamp is newer than the 661 # Only re-use the precomputed checksums if the donestamp is newer than the
663 # file. Do not rely on the mtime of directories, though. If ud.localpath is 662 # file. Do not rely on the mtime of directories, though. If ud.localpath is
664 # a directory, there will probably not be any checksums anyway. 663 # a directory, there will probably not be any checksums anyway.
665 if (os.path.isdir(ud.localpath) or 664 if os.path.exists(ud.donestamp) and (os.path.isdir(ud.localpath) or
666 os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)): 665 os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)):
667 try: 666 try:
668 with open(ud.donestamp, "rb") as cachefile: 667 with open(ud.donestamp, "rb") as cachefile:
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py
index 62b88f1380..d711c77d35 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -20,6 +20,7 @@
20# 20#
21 21
22import unittest 22import unittest
23import hashlib
23import tempfile 24import tempfile
24import subprocess 25import subprocess
25import collections 26import collections
@@ -522,6 +523,109 @@ class FetcherLocalTest(FetcherTest):
522 with self.assertRaises(bb.fetch2.UnpackError): 523 with self.assertRaises(bb.fetch2.UnpackError):
523 self.fetchUnpack(['file://a;subdir=/bin/sh']) 524 self.fetchUnpack(['file://a;subdir=/bin/sh'])
524 525
526class FetcherNoNetworkTest(FetcherTest):
527 def setUp(self):
528 super().setUp()
529 # all test cases are based on not having network
530 self.d.setVar("BB_NO_NETWORK", "1")
531
532 def test_missing(self):
533 string = "this is a test file\n".encode("utf-8")
534 self.d.setVarFlag("SRC_URI", "md5sum", hashlib.md5(string).hexdigest())
535 self.d.setVarFlag("SRC_URI", "sha256sum", hashlib.sha256(string).hexdigest())
536
537 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
538 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
539 fetcher = bb.fetch.Fetch(["http://invalid.yoctoproject.org/test-file.tar.gz"], self.d)
540 with self.assertRaises(bb.fetch2.NetworkAccess):
541 fetcher.download()
542
543 def test_valid_missing_donestamp(self):
544 # create the file in the download directory with correct hash
545 string = "this is a test file\n".encode("utf-8")
546 with open(os.path.join(self.dldir, "test-file.tar.gz"), "wb") as f:
547 f.write(string)
548
549 self.d.setVarFlag("SRC_URI", "md5sum", hashlib.md5(string).hexdigest())
550 self.d.setVarFlag("SRC_URI", "sha256sum", hashlib.sha256(string).hexdigest())
551
552 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
553 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
554 fetcher = bb.fetch.Fetch(["http://invalid.yoctoproject.org/test-file.tar.gz"], self.d)
555 fetcher.download()
556 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
557
558 def test_invalid_missing_donestamp(self):
559 # create an invalid file in the download directory with incorrect hash
560 string = "this is a test file\n".encode("utf-8")
561 with open(os.path.join(self.dldir, "test-file.tar.gz"), "wb"):
562 pass
563
564 self.d.setVarFlag("SRC_URI", "md5sum", hashlib.md5(string).hexdigest())
565 self.d.setVarFlag("SRC_URI", "sha256sum", hashlib.sha256(string).hexdigest())
566
567 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
568 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
569 fetcher = bb.fetch.Fetch(["http://invalid.yoctoproject.org/test-file.tar.gz"], self.d)
570 with self.assertRaises(bb.fetch2.NetworkAccess):
571 fetcher.download()
572 # the existing file should not exist or should have be moved to "bad-checksum"
573 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
574
575 def test_nochecksums_missing(self):
576 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
577 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
578 # ssh fetch does not support checksums
579 fetcher = bb.fetch.Fetch(["ssh://invalid@invalid.yoctoproject.org/test-file.tar.gz"], self.d)
580 # attempts to download with missing donestamp
581 with self.assertRaises(bb.fetch2.NetworkAccess):
582 fetcher.download()
583
584 def test_nochecksums_missing_donestamp(self):
585 # create a file in the download directory
586 with open(os.path.join(self.dldir, "test-file.tar.gz"), "wb"):
587 pass
588
589 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
590 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
591 # ssh fetch does not support checksums
592 fetcher = bb.fetch.Fetch(["ssh://invalid@invalid.yoctoproject.org/test-file.tar.gz"], self.d)
593 # attempts to download with missing donestamp
594 with self.assertRaises(bb.fetch2.NetworkAccess):
595 fetcher.download()
596
597 def test_nochecksums_has_donestamp(self):
598 # create a file in the download directory with the donestamp
599 with open(os.path.join(self.dldir, "test-file.tar.gz"), "wb"):
600 pass
601 with open(os.path.join(self.dldir, "test-file.tar.gz.done"), "wb"):
602 pass
603
604 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
605 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
606 # ssh fetch does not support checksums
607 fetcher = bb.fetch.Fetch(["ssh://invalid@invalid.yoctoproject.org/test-file.tar.gz"], self.d)
608 # should not fetch
609 fetcher.download()
610 # both files should still exist
611 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
612 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
613
614 def test_nochecksums_missing_has_donestamp(self):
615 # create a file in the download directory with the donestamp
616 with open(os.path.join(self.dldir, "test-file.tar.gz.done"), "wb"):
617 pass
618
619 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
620 self.assertTrue(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
621 # ssh fetch does not support checksums
622 fetcher = bb.fetch.Fetch(["ssh://invalid@invalid.yoctoproject.org/test-file.tar.gz"], self.d)
623 with self.assertRaises(bb.fetch2.NetworkAccess):
624 fetcher.download()
625 # both files should still exist
626 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz")))
627 self.assertFalse(os.path.exists(os.path.join(self.dldir, "test-file.tar.gz.done")))
628
525class FetcherNetworkTest(FetcherTest): 629class FetcherNetworkTest(FetcherTest):
526 @skipIfNoNetwork() 630 @skipIfNoNetwork()
527 def test_fetch(self): 631 def test_fetch(self):