import sys, os, string, re, urllib2
if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1:
    sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]
), os.pardir, os.pardir, os.pardir)))
from twisted.python import usage

class Options(usage.Options):
    updates = ('README',
               'twisted/copyright.py',
               'admin/twisted.spec',
               'ChangeLog')
    optParameters = [
     ["type", "t", "alpha", "Type of release -- alpha, RC or final"],
     ["qotr", "q", None, "Quote of the release"],
    ]
    optFlags = [
     ["head", "h", "Start from HEAD"],
     ["manual-changelog", "c", "Enter changelog entry in editor"],
     ["dry-run", "n", "Do nothing"],
    ]
    def opt_update(self, file):
        self.updates = self.updates+(file,)

def getrevision():
    text = urllib2.urlopen('http://cvs.twistedmatrix.com/cvs/README')
    while 1:
        line = text.readline()
        if not line:
            break
        if line.startswith("<br>CVS Tags:"):
            text.readline()
            tag = parsetag(text.readline())
            if tag:
                break
    text.close()
    return tag

def parsetag(tag):
    tag = tag[tag.index('=')+1:]
    tag = tag[tag.index('=')+1:tag.rindex('"')]
    if not tag.startswith('release-'):
        return
    major, minor, patch = tag[tag.index('-')+1:].split('_')
    try:
        patch = int(patch)
    except ValueError:
        m = re.match('(\d+)(.+?)(\d+)', patch)
        patch = m.groups()
    else:
        patch = str(patch), 'final', 1
    return tag, (major, minor, patch)


def strtag(major, minor, patch):
    spatch = ''.join(patch)
    if patch[1]=='final':
        if patch[2]=='1':
            spatch = patch[0]
        else:
            spatch = str(int(patch[0])+1)
    return '.'.join([major, minor, spatch])

def calcnext(version, type):
    major, minor, patch = version
    order=['alpha', 'rc', 'final']
    then, now = order.index(patch[1]), order.index(type)
    if now>then:
        patch = patch[0], type, '1'
    elif now<then:
        patch = str(int(patch[0])+1), type, '1'
    else:
        patch = patch[0], type, str(int(patch[2])+1)
    return strtag(major, minor, patch)

def system(command, do):
    print "running", repr(command)
    if not do:
        return
    n = os.system(command)
    if n:
        sys.exit(n)

def setqotr(qotr, do):
    if qotr is None:
        return
    print "setting quote to", repr(qotr)
    if not do:
        return
    res = []
    fp = iter(file("README"))
    for line in fp:
        res.append(line)
        if line=="Quote of the Release:\n":
            res.append(fp.next()) # blank line
            res.append(qotr)
            for line in fp:
                if line=='\n':
                    break
            res.append(line)
    res = ''.join(res)
    file("README", 'w').write(res)

def run(config):
    tag, version = getrevision()
    command = 'cvs -d :ext:cvs.twistedmatrix.com:/cvs co -d Twisted.CVS'
    if not config['head']:
        command += " -r %s" % tag
    do = not config['dry-run']
    system(command, do)
    old = strtag(*version)
    tag = calcnext(version, config['type'])
    print "next version is", tag
    if config.updates:
        system("cd Twisted.CVS && cvs up -A %s" % ' '.join(config.updates), do)
    command = "cd Twisted.CVS && ./admin/change"
    if not config['manual-changelog']:
        command += " -m 'Releasing Twisted %s'" % tag
    command += " ."
    system(command, do)
    system("Twisted.CVS/admin/release-twisted -o %s -V %s --upver" %
                                                               (old, tag),
           do)
    setqotr(config['qotr'], do)

def main():
    c = Options()
    c.parseOptions()
    run(c)

if __name__=='__main__':
    main()
