Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # -*- coding: utf-8 -*- |
| 3 | |
| 4 | # Runs the daily build of the Python docs on dinsdale.python.org. |
| 5 | # |
| 6 | # Usages: |
| 7 | # |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 8 | # dailybuild.py [-q] |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 9 | # |
| 10 | # without any arguments builds docs for all branches configured in the global |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 11 | # BRANCHES value. -q selects "quick build", which means to build only HTML. |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 12 | # |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 13 | # dailybuild.py [-q] [-d] <checkout> <target> |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 14 | # |
| 15 | # builds one version, where <checkout> is an SVN checkout directory of the |
| 16 | # Python branch to build docs for, and <target> is the directory where the |
| 17 | # result should be placed. If -d is given, the docs are built even if the |
| 18 | # branch is in development mode (i.e. version contains a, b or c). |
| 19 | # |
| 20 | # This script is not run from the checkout, so if you want to change how the |
| 21 | # daily build is run, you must replace it on dinsdale. This is necessary, for |
| 22 | # example, after the release of a new minor version. |
| 23 | # |
| 24 | # 03/2010, Georg Brandl |
| 25 | |
| 26 | import os |
| 27 | import sys |
| 28 | import getopt |
| 29 | |
| 30 | |
| 31 | BUILDROOT = '/home/gbrandl/docbuild' |
Benjamin Peterson | 82c2587 | 2014-02-22 01:32:50 -0500 | [diff] [blame] | 32 | SPHINXBUILD = os.path.join(BUILDROOT, 'sphinx-env/bin/sphinx-build') |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 33 | WWWROOT = '/data/ftp.python.org/pub/docs.python.org' |
| 34 | |
| 35 | BRANCHES = [ |
| 36 | # checkout, target, isdev |
Benjamin Peterson | a4598a3 | 2014-03-30 16:43:11 -0400 | [diff] [blame] | 37 | (BUILDROOT + '/python34', WWWROOT + '/3.4', False), |
| 38 | (BUILDROOT + '/python35', WWWROOT + '/3.5', True), |
Georg Brandl | 0685e14 | 2012-10-28 10:12:47 +0100 | [diff] [blame] | 39 | (BUILDROOT + '/python27', WWWROOT + '/2.7', False), |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 40 | ] |
| 41 | |
| 42 | |
Benjamin Peterson | a4598a3 | 2014-03-30 16:43:11 -0400 | [diff] [blame] | 43 | def _files_changed(old, new): |
| 44 | with open(old, 'rb') as fp1, open(new, 'rb') as fp2: |
| 45 | st1 = os.fstat(fp1.fileno()) |
| 46 | st2 = os.fstat(fp2.fileno()) |
| 47 | if st1.st_size != st2.st_size: |
| 48 | return False |
| 49 | if st1.st_mtime >= st2.st_mtime: |
| 50 | return True |
| 51 | while True: |
| 52 | one = fp1.read(4096) |
| 53 | two = fp2.read(4096) |
| 54 | if one != two: |
| 55 | return False |
| 56 | if one == '': |
| 57 | break |
| 58 | return True |
| 59 | |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 60 | def build_one(checkout, target, isdev, quick): |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 61 | print 'Doc autobuild started in %s' % checkout |
| 62 | os.chdir(checkout) |
Georg Brandl | 2fbe856 | 2012-09-30 09:03:09 +0200 | [diff] [blame] | 63 | print 'Running hg pull --update' |
Benjamin Peterson | 60f0793 | 2014-02-03 13:33:56 -0500 | [diff] [blame] | 64 | os.system('hg pull --update') |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 65 | print 'Running make autobuild' |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 66 | maketarget = 'autobuild-' + ('html' if quick else |
| 67 | ('dev' if isdev else 'stable')) |
Benjamin Peterson | 82c2587 | 2014-02-22 01:32:50 -0500 | [diff] [blame] | 68 | if os.WEXITSTATUS(os.system('cd Doc; make SPHINXBUILD=%s %s' % (SPHINXBUILD, maketarget))) == 2: |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 69 | print '*' * 80 |
| 70 | return |
Benjamin Peterson | a4598a3 | 2014-03-30 16:43:11 -0400 | [diff] [blame] | 71 | print('Computing changed files') |
| 72 | changed = [] |
| 73 | for dirpath, dirnames, filenames in os.walk('Doc/build/html/'): |
| 74 | dir_rel = dirpath[len('Doc/build/html/'):] |
| 75 | for fn in filenames: |
| 76 | local_path = os.path.join(dirpath, fn) |
| 77 | rel_path = os.path.join(dir_rel, fn) |
| 78 | target_path = os.path.join(target, rel_path) |
| 79 | if (os.path.exists(target_path) and |
| 80 | not _files_changed(target_path, local_path)): |
| 81 | changed.append(rel_path) |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 82 | print 'Copying HTML files to %s' % target |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 83 | os.system('cp -a Doc/build/html/* %s' % target) |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 84 | if not quick: |
| 85 | print 'Copying dist files' |
| 86 | os.system('mkdir -p %s/archives' % target) |
| 87 | os.system('cp -a Doc/dist/* %s/archives' % target) |
Benjamin Peterson | a4598a3 | 2014-03-30 16:43:11 -0400 | [diff] [blame] | 88 | changed.append('archives/') |
| 89 | for fn in os.listdir(os.path.join(target, 'archives')): |
| 90 | changed.append('archives/' + fn) |
| 91 | print '%s files changed' % len(changed) |
| 92 | if changed: |
| 93 | target_ino = os.stat(target).st_ino |
| 94 | targets_dir = os.path.dirname(target) |
| 95 | prefixes = [] |
| 96 | for fn in os.listdir(targets_dir): |
| 97 | if os.stat(os.path.join(targets_dir, fn)).st_ino == target_ino: |
| 98 | prefixes.append(fn) |
| 99 | to_purge = [] |
| 100 | for prefix in prefixes: |
| 101 | to_purge.extend(prefix + "/" + p for p in changed) |
| 102 | purge_cmd = 'curl -X PURGE "https://docs.python.org/{%s}"' % ','.join(to_purge) |
| 103 | print("Running CDN purge") |
| 104 | os.system(purge_cmd) |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 105 | print 'Finished' |
| 106 | print '=' * 80 |
| 107 | |
| 108 | def usage(): |
| 109 | print 'Usage:' |
| 110 | print ' %s' % sys.argv[0] |
| 111 | print 'or' |
| 112 | print ' %s [-d] <checkout> <target>' % sys.argv[0] |
| 113 | sys.exit(1) |
| 114 | |
| 115 | |
| 116 | if __name__ == '__main__': |
| 117 | try: |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 118 | opts, args = getopt.getopt(sys.argv[1:], 'dq') |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 119 | except getopt.error: |
| 120 | usage() |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 121 | quick = devel = False |
| 122 | for opt, _ in opts: |
| 123 | if opt == '-q': |
| 124 | quick = True |
| 125 | if opt == '-d': |
| 126 | devel = True |
| 127 | if devel and not args: |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 128 | usage() |
| 129 | if args: |
| 130 | if len(args) != 2: |
| 131 | usage() |
Benjamin Peterson | a4598a3 | 2014-03-30 16:43:11 -0400 | [diff] [blame] | 132 | build_one(os.path.abspath(args[0]), os.path.abspath(args[1]), devel, quick) |
Georg Brandl | 3446583 | 2010-03-13 10:12:39 +0000 | [diff] [blame] | 133 | else: |
Georg Brandl | b70290a | 2012-10-28 08:18:52 +0100 | [diff] [blame] | 134 | for checkout, dest, devel in BRANCHES: |
| 135 | build_one(checkout, dest, devel, quick) |