Make Firefox nightly download more robust.
The script will now only start complaining if we haven't been able to
download anything for days. The script will always touch the file if
the download is successful, so the modified time of the latest
downloaded time is the benchmark of how fresh our Firefox build is.
There can be many days between FF nightly release, sometimes weeks,
so we only care if we managed to download something and not which date
the build is from.
BUG=360516
R=kjellander@chromium.org
Review URL: https://codereview.chromium.org/883273002
git-svn-id: http://src.chromium.org/svn/trunk/deps/third_party/webrtc/webrtc.DEPS@293895 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
diff --git a/download_firefox_nightly.py b/download_firefox_nightly.py
index 9a1f983..bb3d96b 100755
--- a/download_firefox_nightly.py
+++ b/download_firefox_nightly.py
@@ -5,11 +5,14 @@
"""Downloads a Firefox Nightly build for the current platform."""
+import datetime
+import glob
import os
import shutil
import sys
import subprocess
import tarfile
+import time
import zipfile
from optparse import OptionParser
@@ -23,6 +26,87 @@
from mozdownload import scraper
+def _Touch(a_file):
+ with open(a_file, 'a'):
+ os.utime(a_file, None)
+
+
+def _FindFallbackFirefoxBuild(target_dir):
+ firefox_archives = glob.glob(os.path.join(target_dir, '*tar.bz2'))
+ if not firefox_archives:
+ return None
+
+ firefox_archives.sort(key=os.path.getmtime, reverse=True)
+ newest_build = firefox_archives[0]
+ build_age_seconds = time.time() - os.path.getmtime(newest_build)
+ build_age_days = datetime.timedelta(seconds=build_age_seconds).days
+
+ return newest_build, build_age_days
+
+
+def _MaybeDownload(target_dir, force):
+ try:
+ downloader = scraper.DailyScraper(directory=target_dir, version=None)
+ filename = downloader.build_filename(downloader.binary)
+ firefox_archive = os.path.join(target_dir, filename)
+
+ if os.path.exists(firefox_archive) and not force:
+ # Touch the file anyway since we were 'successful', so we can accurately
+ # compute the age of the most recent download attempt and act accordingly
+ # when a download fails later.
+ _Touch(firefox_archive)
+ print 'Skipping download as %s is already downloaded.' % firefox_archive
+ return None
+
+ downloader.download()
+ print 'Downloaded %s' % firefox_archive
+ return firefox_archive
+ except scraper.NotFoundException as exception:
+ print 'Failed to download firefox: %s.' % exception
+ fallback_build, age_days = _FindFallbackFirefoxBuild(target_dir)
+
+ if not fallback_build:
+ raise Exception('We failed to download Firefox and we have no builds to '
+ 'fall back on; failing...')
+ if age_days > 3:
+ raise Exception('We have failed to download firefox builds for more '
+ 'than 3 days now: failing so someone looks at it. The '
+ 'most recent build we have is %d days old.' % age_days)
+
+ print 'Using %s instead; it is %d days old.' % (fallback_build, age_days)
+ return fallback_build
+
+
+def _ExtractArchive(firefox_archive, target_dir):
+ # TODO(phoglund): implement on win/mac. See http://crbug.com/454303.
+ if sys.platform == 'darwin':
+ print "Disabled on mac..."
+ return 0
+ volume = '/Volumes/Nightly'
+ firefox_executable = '%s/FirefoxNightly.app' % target_dir
+
+ # Unmount any previous downloads.
+ subprocess.call(['hdiutil', 'detach', volume])
+
+ subprocess.check_call(['hdiutil', 'attach', firefox_archive])
+ shutil.copytree('%s/FirefoxNightly.app' % volume, firefox_executable)
+ subprocess.check_call(['hdiutil', 'detach', volume])
+ elif sys.platform == 'linux2':
+ tar_archive = tarfile.open(firefox_archive, 'r:bz2')
+ tar_archive.extractall(path=target_dir)
+ elif sys.platform == 'win32':
+ print "Disabled on win..."
+ return 0
+ zip_archive = zipfile.ZipFile(firefox_archive)
+ zip_archive.extractall(path=target_dir)
+ else:
+ print >> sys.stderr, 'Unsupported platform: %s' % sys.platform
+ return 1
+
+ print 'Extracted %s' % firefox_archive
+ return 0
+
+
def main():
usage = 'usage: %prog -t <target_dir>'
parser = OptionParser(usage)
@@ -40,45 +124,9 @@
if not os.path.isdir(target_dir):
os.mkdir(target_dir)
- downloader = scraper.DailyScraper(directory=target_dir, version=None)
- firefox_archive = os.path.join(target_dir,
- downloader.build_filename(downloader.binary))
-
- if os.path.exists(firefox_archive) and not options.force:
- print 'Skipping download as %s is already downloaded.' % firefox_archive
- return 0
-
- downloader.download()
- print 'Downloaded %s' % firefox_archive
-
- # Extract the archive.
- # TODO(phoglund): implement on win/mac
- if sys.platform == 'darwin':
- print "Temporarily disabled on mac..."
- return 0
- volume = '/Volumes/Nightly'
- firefox_executable = '%s/FirefoxNightly.app' % target_dir
-
- # Unmount any previous downloads.
- subprocess.call(['hdiutil', 'detach', volume])
-
- subprocess.check_call(['hdiutil', 'attach', firefox_archive])
- shutil.copytree('%s/FirefoxNightly.app' % volume, firefox_executable)
- subprocess.check_call(['hdiutil', 'detach', volume])
- elif sys.platform == 'linux2':
- tar_archive = tarfile.open(firefox_archive, 'r:bz2')
- tar_archive.extractall(path=target_dir)
- elif sys.platform == 'win32':
- print "Temporarily disabled on win..."
- return 0
- zip_archive = zipfile.ZipFile(firefox_archive)
- zip_archive.extractall(path=target_dir)
- else:
- print >> sys.stderr, 'Unsupported platform: %s' % sys.platform
- return 1
-
- print 'Extracted %s' % firefox_archive
- return 0
+ firefox_archive = _MaybeDownload(target_dir, options.force)
+ if firefox_archive:
+ return _ExtractArchive(firefox_archive, target_dir)
if __name__ == '__main__':
sys.exit(main())