import distutils.dir_util
import os
import shutil
import sys
import tempfile
import time
from common import *
DOC_ARGS = '--no-deps'
DOC_FEATURES = ""
DOC_TARGET_BRANCH = 'gh-pages'
DOC_PKG_DIR = None
DOC_TOOLCHAIN = None
TEMP_CHECKOUT_PREFIX = 'gh-pages-checkout-'
TEMP_OUTPUT_PREFIX = 'gh-pages-generated-'
TRACE_UPDATE_DOCS = os.environ.get('TRACE_UPDATE_DOCS', '') != ''
def copytree(src, dst):
msg_trace('copytree(%r, %r)' % (src, dst))
distutils.dir_util.copy_tree(src=src, dst=dst)
def really_rmtree(path):
msg_trace('really_rmtree(%r)' % path)
WAIT_TIME_SECS = 1.0
MAX_TRIES = 10
def on_error(func, path, exc_info):
import stat
if not os.access(path, os.W_OK):
os.chmod(path, stat.S_IWUSR)
func(path)
else:
raise
for _ in range(MAX_TRIES):
failed = True
try:
msg_trace('shutil.rmtree(%r)' % path)
shutil.rmtree(path, onerror=on_error)
failed = False
except WindowsError:
time.sleep(WAIT_TIME_SECS)
if not failed: return
msg('Warning: failed to remove directory %r' % path)
def init_doc_branch():
msg("Initialising %s branch" % DOC_TARGET_BRANCH)
dir = os.getcwd()
msg_trace('dir = %r' % dir)
tmp = tempfile.mkdtemp(prefix=TEMP_CHECKOUT_PREFIX)
msg_trace('tmp = %r' % tmp)
try:
msg("Cloning into a temporary directory...")
sh('git init -q "%s"' % tmp)
msg_trace('os.chdir(%r)' % tmp)
os.chdir(tmp)
sh('git checkout -q --orphan "%s"' % DOC_TARGET_BRANCH)
sh('git commit -qm "Initial commit." --allow-empty')
sh('git remote add origin "%s"' % dir)
sh('git push -q origin gh-pages')
finally:
msg('Cleaning up...')
msg_trace('os.chdir(%r)' % dir)
os.chdir(dir)
msg_trace('shutil.rmtree(%r)' % tmp)
really_rmtree(tmp)
msg('%s is ready. Continuing.' % DOC_TARGET_BRANCH)
def gen_doc_bare(tmp1, tmp2):
msg("Generating documentation...")
args = '%s --features="%s"' % (DOC_ARGS, DOC_FEATURES)
if DOC_TOOLCHAIN is not None:
toolchain = "%s run %s " % (RUSTUP, DOC_TOOLCHAIN)
else:
toolchain = ""
sh('%scargo doc %s' % (toolchain, args))
tmp1_target_doc = '%s/target/doc' % tmp1
msg_trace('shutil.move(%r, %r)' % (tmp1_target_doc, tmp2))
shutil.move(tmp1_target_doc, tmp2)
def gen_doc_pkg(tmp1, tmp2, doc_pkg):
if DOC_FEATURES != "":
msg("Error: doc packages don't support features.")
sys.exit(1)
import json
old_dir = os.getcwd()
msg("Generating documentation from doc package...")
msg_trace('doc_pkg = %r' % doc_pkg)
msg_trace('os.chdir(%r)' % doc_pkg)
try:
os.chdir(doc_pkg)
manifest_str = sh_eval('cargo read-manifest --manifest-path "%s"'
% os.path.join(doc_pkg, 'Cargo.toml'))
manifest = json.loads(manifest_str)
if DOC_TOOLCHAIN is not None:
toolchain = "%s run %s " % (RUSTUP, DOC_TOOLCHAIN)
else:
toolchain = ""
packages = " ".join("--package %s" % d['name'] for d in manifest['dependencies'])
sh('%scargo doc %s' % (toolchain, packages))
target_doc = os.path.join(doc_pkg, 'target/doc')
msg_trace('shutil.move(%r, %r)' % (target_doc, tmp2))
shutil.move(target_doc, tmp2)
finally:
msg_trace('os.chdir(%r)' % old_dir)
os.chdir(old_dir)
def main():
load_globals_from_metadata('update-docs', globals(),
{
'DOC_ARGS',
'DOC_FEATURES',
'DOC_TARGET_BRANCH',
'DOC_PKG_DIR',
'DOC_TOOLCHAIN',
'TEMP_CHECKOUT_PREFIX',
'TEMP_OUTPUT_PREFIX',
})
if sh_eval('git symbolic-ref --short HEAD') != u'master':
msg('Not on master; doing nothing.')
return 0
branches = {b[2:].strip() for b in sh_eval('git branch', dont_strip=True).splitlines()}
msg_trace('branches = %r' % branches)
if DOC_TARGET_BRANCH not in branches:
init_doc_branch()
last_rev = sh_eval('git rev-parse HEAD')
last_msg = sh_eval('git log -1 --pretty=%B')
msg_trace('last_rev = %r' % last_rev)
msg_trace('last_msg = %r' % last_msg)
dir = os.getcwd()
msg_trace('dir = %r' % dir)
tmp1 = tempfile.mkdtemp(prefix=TEMP_CHECKOUT_PREFIX)
tmp2 = tempfile.mkdtemp(prefix=TEMP_OUTPUT_PREFIX)
msg_trace('tmp1 = %r' % tmp1)
msg_trace('tmp2 = %r' % tmp2)
try:
msg("Cloning into a temporary directory...")
sh('git clone -qb "%s" "%s" "%s"' % (DOC_TARGET_BRANCH, dir, tmp1))
msg_trace('os.chdir(%r)' % tmp1)
os.chdir(tmp1)
sh('git checkout -q master')
if DOC_PKG_DIR is not None:
gen_doc_pkg(tmp1, tmp2, os.path.abspath(DOC_PKG_DIR))
else:
gen_doc_bare(tmp1, tmp2)
msg('Updating %s...' % DOC_TARGET_BRANCH)
sh('git checkout -q "%s"' % DOC_TARGET_BRANCH)
sh('git clean -dfq')
tmp2_doc = '%s/doc' % tmp2
msg_trace('copytree(%r, %r)' % (tmp2_doc, './doc'))
copytree(tmp2_doc, './doc')
msg('Committing changes...')
sh('git add .')
sh('git commit --amend -m "Update docs for %s" -m "%s"' % (last_rev[:7], last_msg))
sh('git push -fqu origin "%s"' % DOC_TARGET_BRANCH)
finally:
msg('Cleaning up...')
msg_trace('os.chdir(%r)' % dir)
os.chdir(dir)
msg_trace('shutil.rmtree(%r)' % tmp2)
really_rmtree(tmp2)
msg_trace('shutil.rmtree(%r)' % tmp1)
really_rmtree(tmp1)
msg('Publishing...')
sh('git push -f origin "%s"' % DOC_TARGET_BRANCH)
msg('Done.')
if __name__ == '__main__':
sys.exit(main())