"""Tag the sandbox for release, make source and doc tarballs.

Requires Python 2.6

Example of invocation (use to test the script):
python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-dev

When testing this script:
python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-dev

Example of invocation when doing a release:
python makerelease.py 0.5.0 0.6.0-dev
"""
import os.path
import subprocess
import sys
import doxybuild
import subprocess
import xml.etree.ElementTree as ElementTree
import shutil
import urllib2
import tempfile
import os
import time
from devtools import antglob, fixeol, tarball
import amalgamate

SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/'
SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp'
SCONS_LOCAL_URL = 'http://sourceforge.net/projects/scons/files/scons-local/1.2.0/scons-local-1.2.0.tar.gz/download'
SOURCEFORGE_PROJECT = 'jsoncpp'

def set_version( version ):
    with open('version','wb') as f:
        f.write( version.strip() )

def rmdir_if_exist( dir_path ):
    if os.path.isdir( dir_path ):
        shutil.rmtree( dir_path )

class SVNError(Exception):
    pass

def svn_command( command, *args ):
    cmd = ['svn', '--non-interactive', command] + list(args)
    print 'Running:', ' '.join( cmd )
    process = subprocess.Popen( cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT )
    stdout = process.communicate()[0]
    if process.returncode:
        error = SVNError( 'SVN command failed:\n' + stdout )
        error.returncode = process.returncode
        raise error
    return stdout

def check_no_pending_commit():
    """Checks that there is no pending commit in the sandbox."""
    stdout = svn_command( 'status', '--xml' )
    etree = ElementTree.fromstring( stdout )
    msg = []
    for entry in etree.getiterator( 'entry' ):
        path = entry.get('path')
        status = entry.find('wc-status').get('item')
        if status != 'unversioned' and path != 'version':
            msg.append( 'File "%s" has pending change (status="%s")' % (path, status) )
    if msg:
        msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!' )
    return '\n'.join( msg )

def svn_join_url( base_url, suffix ):
    if not base_url.endswith('/'):
        base_url += '/'
    if suffix.startswith('/'):
        suffix = suffix[1:]
    return base_url + suffix

def svn_check_if_tag_exist( tag_url ):
    """Checks if a tag exist.
    Returns: True if the tag exist, False otherwise.
    """
    try:
        list_stdout = svn_command( 'list', tag_url )
    except SVNError, e:
        if e.returncode != 1 or not str(e).find('tag_url'):
            raise e
        # otherwise ignore error, meaning tag does not exist
        return False
    return True

def svn_commit( message ):
    """Commit the sandbox, providing the specified comment.
    """
    svn_command( 'ci', '-m', message )

def svn_tag_sandbox( tag_url, message ):
    """Makes a tag based on the sandbox revisions.
    """
    svn_command( 'copy', '-m', message, '.', tag_url )

def svn_remove_tag( tag_url, message ):
    """Removes an existing tag.
    """
    svn_command( 'delete', '-m', message, tag_url )

def svn_export( tag_url, export_dir ):
    """Exports the tag_url revision to export_dir.
       Target directory, including its parent is created if it does not exist.
       If the directory export_dir exist, it is deleted before export proceed.
    """
    rmdir_if_exist( export_dir )
    svn_command( 'export', tag_url, export_dir )

def fix_sources_eol( dist_dir ):
    """Set file EOL for tarball distribution.
    """
    print 'Preparing exported source file EOL for distribution...'
    prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
    win_sources = antglob.glob( dist_dir, 
        includes = '**/*.sln **/*.vcproj',
        prune_dirs = prune_dirs )
    unix_sources = antglob.glob( dist_dir,
        includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.in
        sconscript *.json *.expected AUTHORS LICENSE''',
        excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*',
        prune_dirs = prune_dirs )
    for path in win_sources:
        fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\r\n' )
    for path in unix_sources:
        fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\n' )

def download( url, target_path ):
    """Download file represented by url to target_path.
    """
    f = urllib2.urlopen( url )
    try:
        data = f.read()
    finally:
        f.close()
    fout = open( target_path, 'wb' )
    try:
        fout.write( data )
    finally:
        fout.close()

def check_compile( distcheck_top_dir, platform ):
    cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check']
    print 'Running:', ' '.join( cmd )
    log_path = os.path.join( distcheck_top_dir, 'build-%s.log' % platform )
    flog = open( log_path, 'wb' )
    try:
        process = subprocess.Popen( cmd,
                                    stdout=flog,
                                    stderr=subprocess.STDOUT,
                                    cwd=distcheck_top_dir )
        stdout = process.communicate()[0]
        status = (process.returncode == 0)
    finally:
        flog.close()
    return (status, log_path)

def write_tempfile( content, **kwargs ):
    fd, path = tempfile.mkstemp( **kwargs )
    f = os.fdopen( fd, 'wt' )
    try:
        f.write( content )
    finally:
        f.close()
    return path

class SFTPError(Exception):
    pass

def run_sftp_batch( userhost, sftp, batch, retry=0 ):
    path = write_tempfile( batch, suffix='.sftp', text=True )
    # psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc
    cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost]
    error = None
    for retry_index in xrange(0, max(1,retry)):
        heading = retry_index == 0 and 'Running:' or 'Retrying:'
        print heading, ' '.join( cmd )
        process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
        stdout = process.communicate()[0]
        if process.returncode != 0:
            error = SFTPError( 'SFTP batch failed:\n' + stdout )
        else:
            break
    if error:
        raise error
    return stdout

def sourceforge_web_synchro( sourceforge_project, doc_dir,
                             user=None, sftp='sftp' ):
    """Notes: does not synchronize sub-directory of doc-dir.
    """
    userhost = '%s,%s@web.sourceforge.net' % (user, sourceforge_project)
    stdout = run_sftp_batch( userhost, sftp, """
cd htdocs
dir
exit
""" )
    existing_paths = set()
    collect = 0
    for line in stdout.split('\n'):
        line = line.strip()
        if not collect and line.endswith('> dir'):
            collect = True
        elif collect and line.endswith('> exit'):
            break
        elif collect == 1:
            collect = 2
        elif collect == 2:
            path = line.strip().split()[-1:]
            if path and path[0] not in ('.', '..'):
                existing_paths.add( path[0] )
    upload_paths = set( [os.path.basename(p) for p in antglob.glob( doc_dir )] )
    paths_to_remove = existing_paths - upload_paths
    if paths_to_remove:
        print 'Removing the following file from web:'
        print '\n'.join( paths_to_remove )
        stdout = run_sftp_batch( userhost, sftp, """cd htdocs
rm %s
exit""" % ' '.join(paths_to_remove) )
    print 'Uploading %d files:' % len(upload_paths)
    batch_size = 10
    upload_paths = list(upload_paths)
    start_time = time.time()
    for index in xrange(0,len(upload_paths),batch_size):
        paths = upload_paths[index:index+batch_size]
        file_per_sec = (time.time() - start_time) / (index+1)
        remaining_files = len(upload_paths) - index
        remaining_sec = file_per_sec * remaining_files
        print '%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)
        run_sftp_batch( userhost, sftp, """cd htdocs
lcd %s
mput %s
exit""" % (doc_dir, ' '.join(paths) ), retry=3 )

def sourceforge_release_tarball( sourceforge_project, paths, user=None, sftp='sftp' ):
    userhost = '%s,%s@frs.sourceforge.net' % (user, sourceforge_project)
    run_sftp_batch( userhost, sftp, """
mput %s
exit
""" % (' '.join(paths),) )


def main():
    usage = """%prog release_version next_dev_version
Update 'version' file to release_version and commit.
Generates the document tarball.
Tags the sandbox revision with release_version.
Update 'version' file to next_dev_version and commit.

Performs an svn export of tag release version, and build a source tarball.    

Must be started in the project top directory.

Warning: --force should only be used when developping/testing the release script.
"""
    from optparse import OptionParser
    parser = OptionParser(usage=usage)
    parser.allow_interspersed_args = False
    parser.add_option('--dot', dest="dot_path", action='store', default=doxybuild.find_program('dot'),
        help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""")
    parser.add_option('--doxygen', dest="doxygen_path", action='store', default=doxybuild.find_program('doxygen'),
        help="""Path to Doxygen tool. [Default: %default]""")
    parser.add_option('--force', dest="ignore_pending_commit", action='store_true', default=False,
        help="""Ignore pending commit. [Default: %default]""")
    parser.add_option('--retag', dest="retag_release", action='store_true', default=False,
        help="""Overwrite release existing tag if it exist. [Default: %default]""")
    parser.add_option('-p', '--platforms', dest="platforms", action='store', default='',
        help="""Comma separated list of platform passed to scons for build check.""")
    parser.add_option('--no-test', dest="no_test", action='store_true', default=False,
        help="""Skips build check.""")
    parser.add_option('--no-web', dest="no_web", action='store_true', default=False,
        help="""Do not update web site.""")
    parser.add_option('-u', '--upload-user', dest="user", action='store',
                      help="""Sourceforge user for SFTP documentation upload.""")
    parser.add_option('--sftp', dest='sftp', action='store', default=doxybuild.find_program('psftp', 'sftp'),
                      help="""Path of the SFTP compatible binary used to upload the documentation.""")
    parser.enable_interspersed_args()
    options, args = parser.parse_args()

    if len(args) != 2:
        parser.error( 'release_version missing on command-line.' )
    release_version = args[0]
    next_version = args[1]

    if not options.platforms and not options.no_test:
        parser.error( 'You must specify either --platform or --no-test option.' )

    if options.ignore_pending_commit:
        msg = ''
    else:
        msg = check_no_pending_commit()
    if not msg:
        print 'Setting version to', release_version
        set_version( release_version )
        svn_commit( 'Release ' + release_version )
        tag_url = svn_join_url( SVN_TAG_ROOT, release_version )
        if svn_check_if_tag_exist( tag_url ):
            if options.retag_release:
                svn_remove_tag( tag_url, 'Overwriting previous tag' )
            else:
                print 'Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url
                sys.exit( 1 )
        svn_tag_sandbox( tag_url, 'Release ' + release_version )

        print 'Generated doxygen document...'
##        doc_dirname = r'jsoncpp-api-html-0.5.0'
##        doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz'
        doc_tarball_path, doc_dirname = doxybuild.build_doc( options, make_release=True )
        doc_distcheck_dir = 'dist/doccheck'
        tarball.decompress( doc_tarball_path, doc_distcheck_dir )
        doc_distcheck_top_dir = os.path.join( doc_distcheck_dir, doc_dirname )
        
        export_dir = 'dist/export'
        svn_export( tag_url, export_dir )
        fix_sources_eol( export_dir )
        
        source_dir = 'jsoncpp-src-' + release_version
        source_tarball_path = 'dist/%s.tar.gz' % source_dir
        print 'Generating source tarball to', source_tarball_path
        tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir )

        amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir
        print 'Generating amalgamation source tarball to', amalgamation_tarball_path
        amalgamation_dir = 'dist/amalgamation'
        amalgamate.amalgamate_source( export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h' )
        amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version
        tarball.make_tarball( amalgamation_tarball_path, [amalgamation_dir],
                              amalgamation_dir, prefix_dir=amalgamation_source_dir )

        # Decompress source tarball, download and install scons-local
        distcheck_dir = 'dist/distcheck'
        distcheck_top_dir = distcheck_dir + '/' + source_dir
        print 'Decompressing source tarball to', distcheck_dir
        rmdir_if_exist( distcheck_dir )
        tarball.decompress( source_tarball_path, distcheck_dir )
        scons_local_path = 'dist/scons-local.tar.gz'
        print 'Downloading scons-local to', scons_local_path
        download( SCONS_LOCAL_URL, scons_local_path )
        print 'Decompressing scons-local to', distcheck_top_dir
        tarball.decompress( scons_local_path, distcheck_top_dir )

        # Run compilation
        print 'Compiling decompressed tarball'
        all_build_status = True
        for platform in options.platforms.split(','):
            print 'Testing platform:', platform
            build_status, log_path = check_compile( distcheck_top_dir, platform )
            print 'see build log:', log_path
            print build_status and '=> ok' or '=> FAILED'
            all_build_status = all_build_status and build_status
        if not build_status:
            print 'Testing failed on at least one platform, aborting...'
            svn_remove_tag( tag_url, 'Removing tag due to failed testing' )
            sys.exit(1)
        if options.user:
            if not options.no_web:
                print 'Uploading documentation using user', options.user
                sourceforge_web_synchro( SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp )
                print 'Completed documentation upload'
            print 'Uploading source and documentation tarballs for release using user', options.user
            sourceforge_release_tarball( SOURCEFORGE_PROJECT,
                                         [source_tarball_path, doc_tarball_path],
                                         user=options.user, sftp=options.sftp )
            print 'Source and doc release tarballs uploaded'
        else:
            print 'No upload user specified. Web site and download tarbal were not uploaded.'
            print 'Tarball can be found at:', doc_tarball_path

        # Set next version number and commit            
        set_version( next_version )
        svn_commit( 'Released ' + release_version )
    else:
        sys.stderr.write( msg + '\n' )
 
if __name__ == '__main__':
    main()
