#!/usr/bin/python
#
# Creates diffs (with log) from a working SVN_HEAD_DIRS, stepping back to
# a given date. This tool can be used to generate 'solid' patches "from date
# - to date" in a subversion directory.
#
# Note: this script doesn't use subversion bindings internally, instead it
# calls the 'svn' command sequentially.
#

import os
import sys
import commands
import datetime

# configuration (head dirs (more than 1 if build was moved), date)
svn_head_dirs = [ 'kpdf_head_aftermove', 'kpdf_head_premove' ]
svn_branch_date = '2005-02-12'

# subroutines
def repo_date():
    val = commands.getoutput( 'svn info | grep "Changed Date" | awk -F\  \'{print $4}\'' )
    return val

def comment_prev():
    comment = commands.getoutput( 'svn log -r COMMITTED | tr \- \_ | tr \+ \|' )
    return comment

def diff_prev():
    diff = commands.getoutput( 'svn diff -r PREV:BASE' )
    return diff

def update_to_prev():
    rev = commands.getoutput( 'svn up -r PREV | tail -n 1 | awk -F\  \'{print $4}\'' )
    return rev

def enter_next_dir( base, idx ):
    os.chdir( base )
    nextDir = svn_head_dirs[ idx ]
    if not nextDir:
	print 'No more fallback directories!'
	sys.exit( 1 )
    if not os.path.isdir( nextDir ):
	print 'The svn directory ' + nextDir + ' doesn\'t exist'
	sys.exit( 1 )
    os.chdir( nextDir )

def num_to_string( n ):
    s = ''
    if n < 100:
	s = '0'
    if n < 10:
	s = s + '0'
    return s + str( n )

### main program ###

# enter in svn_head_dir
svn_head_dir_current = 0
baseDir = os.getcwd()
enter_next_dir( baseDir, svn_head_dir_current )
svn_head_dir_current = svn_head_dir_current + 1

# find out datetime for given date
ymd = svn_branch_date.split( '-' )
minDate = datetime.date( int(ymd[0]), int(ymd[1]), int(ymd[2]) )
if minDate > datetime.date.today():
    print 'The \'previous date\' is beyond today! :-)'
    sys.exit( 1 )

# loop making diffs and going backwards until svn_branch_date is reached
print 'Creating Patches:'
files = []
counter = 0
reachedDate = False
while ( not reachedDate ):
    # be verbose...
    counter = counter + 1
    print '  creating patch \'' + str( counter ) + '\': ',
    sys.stdout.flush()

    # get commit log and diff
    comment = comment_prev()
    print '.',
    sys.stdout.flush()
    diff = diff_prev()
    print '.',
    sys.stdout.flush()

    # update repository to previous version
    rev = update_to_prev()
    if 'replace' in rev:
	enter_next_dir( baseDir, svn_head_dir_current )
	print '\nSwitching to directory ' + str( svn_head_dir_current ) + '!'
	svn_head_dir_current = svn_head_dir_current + 1
	continue
    print '.',
    sys.stdout.flush()
    
    # write patch, with comment, to file
    name = str('/tmp/patch' + str( rev ) + 'diff')
    logfile = file( name, 'w' )
    logfile.write( comment + '\n' + diff )
    logfile.close()
    files = files + [ name ]
    print '.',
    sys.stdout.flush()
    
    # get repository date and continue looping if greater than mindate
    repositoryDateString = repo_date()
    ymd = repositoryDateString.split( '-' )
    repositoryDate = datetime.date( int(ymd[0]), int(ymd[1]), int(ymd[2]) )
    reachedDate = repositoryDate < minDate
    print '. [' + repositoryDateString + ']'
    sys.stdout.flush()
print 'ok.'

# revert list
print 'Naming Files: '
os.chdir( baseDir );
for file in files:
    commands.getoutput( 'mv ' + file + ' ./patch_' + num_to_string( counter ) + '.diff' )
    counter = counter - 1
    print '.',
    sys.stdout.flush()
print '\nok.'
