1#!/usr/bin/env python
2"""Script to commit the doc build outputs into the github-pages repo.
3
4Use:
5
6  gh-pages.py [tag]
7
8If no tag is given, the current output of 'git describe' is used.  If given,
9that is how the resulting directory will be named.
10
11In practice, you should use either actual clean tags from a current build or
12something like 'current' as a stable URL for the mest current version of the """
13
14#-----------------------------------------------------------------------------
15# Imports
16#-----------------------------------------------------------------------------
17import os
18import re
19import shutil
20import sys
21from os import chdir as cd
22
23from subprocess import Popen, PIPE, CalledProcessError, check_call
24
25#-----------------------------------------------------------------------------
26# Globals
27#-----------------------------------------------------------------------------
28
29pages_dir = 'gh-pages'
30html_dir = 'build/html'
31pdf_dir = 'build/latex'
32pages_repo = 'https://github.com/scikit-image/docs.git'
33
34#-----------------------------------------------------------------------------
35# Functions
36#-----------------------------------------------------------------------------
37def sh(cmd):
38    """Execute command in a subshell, return status code."""
39    return check_call(cmd, shell=True)
40
41
42def sh2(cmd):
43    """Execute command in a subshell, return stdout.
44
45    Stderr is unbuffered from the subshell.x"""
46    p = Popen(cmd, stdout=PIPE, shell=True)
47    out = p.communicate()[0]
48    retcode = p.returncode
49    if retcode:
50        print(out.rstrip())
51        raise CalledProcessError(retcode, cmd)
52    else:
53        return out.rstrip()
54
55
56def sh3(cmd):
57    """Execute command in a subshell, return stdout, stderr
58
59    If anything appears in stderr, print it out to sys.stderr"""
60    p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
61    out, err = p.communicate()
62    retcode = p.returncode
63    if retcode:
64        raise CalledProcessError(retcode, cmd)
65    else:
66        return out.rstrip(), err.rstrip()
67
68
69def init_repo(path):
70    """clone the gh-pages repo if we haven't already."""
71    sh("git clone %s %s"%(pages_repo, path))
72    here = os.getcwd()
73    cd(path)
74    sh('git checkout gh-pages')
75    cd(here)
76
77#-----------------------------------------------------------------------------
78# Script starts
79#-----------------------------------------------------------------------------
80if __name__ == '__main__':
81    # find the version number from skimage/__init__.py
82    setup_lines = open('../skimage/__init__.py').readlines()
83    tag = 'vUndefined'
84    for l in setup_lines:
85        if l.startswith('__version__'):
86            tag = l.split("'")[1]
87
88            if "dev" in tag:
89                tag = "dev"
90            else:
91                # Rename e.g. 0.9.0 to 0.9.x
92                tag = '.'.join(tag.split('.')[:-1] + ['x'])
93
94            break
95
96
97    startdir = os.getcwd()
98    if not os.path.exists(pages_dir):
99        # init the repo
100        init_repo(pages_dir)
101    else:
102        # ensure up-to-date before operating
103        cd(pages_dir)
104        sh('git checkout gh-pages')
105        sh('git pull')
106        cd(startdir)
107
108    dest = os.path.join(pages_dir, tag)
109    # This is pretty unforgiving: we unconditionally nuke the destination
110    # directory, and then copy the html tree in there
111    shutil.rmtree(dest, ignore_errors=True)
112    shutil.copytree(html_dir, dest)
113    # copy pdf file into tree
114    #shutil.copy(pjoin(pdf_dir, 'scikits.image.pdf'), pjoin(dest, 'scikits.image.pdf'))
115
116    try:
117        cd(pages_dir)
118        status = sh2('git status | head -1')
119        branch = re.match(b'On branch (.*)$', status).group(1)
120        if branch != b'gh-pages':
121            e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir,
122                                                                 branch)
123            raise RuntimeError(e)
124        sh("touch .nojekyll")
125        sh('git add .nojekyll')
126        sh('git add index.html')
127        sh('git add --all %s' % tag)
128
129        status = sh2('git status | tail -1')
130        if not re.match(b'nothing to commit', status):
131            sh2('git commit -m"Updated doc release: %s"' % tag)
132        else:
133            print('\n! Note: no changes to commit\n')
134
135        print('Most recent commit:')
136        sys.stdout.flush()
137        sh('git --no-pager log --oneline HEAD~1..')
138    finally:
139        cd(startdir)
140
141    print('')
142    print('Now verify the build in: %r' % dest)
143    print("If everything looks good, run 'git push' inside doc/gh-pages.")
144