#!/usr/bin/python
#-*- coding: UTF-8 -*-
import os.path
import sys
import pysvn
import time

class FreezingMover(object):
    def __init__(self):
        self.client = pysvn.Client()

    def ReplacedBase(self, path):
		return self.dst + path[len(self.src):]

    def CreateTag(self, src, dst):
        self.src = os.path.abspath(os.path.join('.', src))
        self.dst = os.path.abspath(os.path.join('.', dst))

        print 'Tagging %s to %s' % (self.src, self.dst)
        print '  Scanning external references...'
        remap = { }
        props = self.client.propget('svn:externals', self.src, recurse=True)
        for k, v in props.iteritems():
            extvals = []
            print '    *', k, '->', self.ReplacedBase(k)
            for ext in v.strip().split('\n'):
                vals = ext.split()
                rev, uri, dirname = self.__ExtractInfos(k, vals)
                extvals.append('%s@%s %s' % (uri, rev, dirname))
            remap[self.ReplacedBase(k)] = '\n'.join(extvals)

        # do svn copy
        print 'Executing \'svn copy %s %s\'...' % (self.src, self.dst)
        self.client.copy(self.src, self.dst)

        # freeze svn:externals
        print 'Updating svn:externals ...'
        for k, v in remap.iteritems():
#            print v, k
            self.client.propset('svn:externals', v, k)

    def __ExtractInfos(self, base, props):
        rev, uri, dirname, fixed = '', '', '', False
        if ':' in props[-1]:
            rev, uri, dirname, fixed = self.__ParseOldSyntax(base, props)
        else:
            rev, uri, dirname, fixed = self.__ParseNewSyntax(base, props)

        if fixed:
            print '      > %s: %s (@rev %s; fixed already)' % (dirname, uri, rev)
        else:
            print '      > %s: %s (@rev %s)' % (dirname, uri, rev)
        return rev, uri, dirname

    def __ParseOldSyntax(self, base, props):
        if len(props) == 2: # dirname, uri
            info = self.client.info2(os.path.join(base, props[0]))[0]
            return info[1]['rev'].number, props[1], props[0], False
        else:
            if len(props) == 3: # dirname -rRev uri
                return props[1][2:], props[2], props[0], True
            else: # dirname -r rev uri
                assert(len(props) == 4)
                return props[2], props[3], props[0], True
    
    def __ParseNewSyntax(self, base, props):
        if len(props) == 2: # uri[@rev] dirname
            if '@' in props[0]: # uri@rev dirname
                pegged = props[0].split('@', 1)
                return pegged[1], pegged[0], props[1], True
            else: # uri dirname
                info = self.client.info2(os.path.join(base,props[1]))[0]
                return info[1]['rev'].number, props[0], props[1], False
        else: # -r rev uri dirname
            if len(props) == 3:
                return props[0][2:], props[1], props[2], True
            else:
                assert(len(props) == 4)
                return props[1], props[2], props[3], True

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print 'Usage: %s src dst' % os.path.basename(sys.argv[0])
        exit(-1)
    start = time.time()
    fm = FreezingMover()
    fm.CreateTag(sys.argv[1], sys.argv[2])
    done = time.time()
    print "Time elapsed: %.2f" % (done - start)

