#!/usr/bin/env python3

r'''Convert an hg-exported patch to a patch suitable for use by git am.

>>> hg_patch_to_git_patch(StringIO('# HG changeset patch\n# User Foo <foo@bar.com>\n# Node ID deadbeef\n# Parent cafebabe\nCommit\n\nMsg\n\ndiff -\ndiffdiff'))
From: Foo <foo@bar.com>
Subject: Commit
<BLANKLINE>
Msg
<BLANKLINE>
diff -
diffdiff

'''

from __future__ import print_function
import sys
from io import StringIO

def hg_patch_to_git_patch(hg_patch_file):
    hg_patch = hg_patch_file.read().split('\n')

    # First, skip any blank lines.
    for i in range(len(hg_patch)):
        line = hg_patch[i]
        if line != "":
            break

    author = None
    date = None # not currently used
    for i in range(i, len(hg_patch)):
        line = hg_patch[i]
        if not line.startswith('#'):
            break

        if line.startswith('# User '):
            author = line[len('# User '):]
        if line.startswith('# Date '): 
            date = line[len('# Date '):]
            epoch, utcoffset = date.split()
            # Mercurial's timezone offsets are negative and in seconds
            # We could also convert the epoch to RFC822 format, but
            # git am is happy with it.
            utcoffset = int(utcoffset) / 60
            date = '%s %s%02d%02d' % (
                epoch,
                '+' if utcoffset <= 0 else '-',
                abs(utcoffset) // 60,
                abs(utcoffset) % 60,
            )

    commit_msg = []
    for i in range(i, len(hg_patch)):
        line = hg_patch[i]
        if line.startswith('diff -'):
            break
        commit_msg.append(hg_patch[i]) 

    if len(commit_msg) == 1 and not commit_msg[0].strip():
        commit_msg[0] = hg_patch_file.name

    if len(commit_msg) > 1 and not commit_msg[1].strip():
        del commit_msg[1]

    # Remove blank lines at the end of the commit message.
    while commit_msg and not commit_msg[-1].strip():
        del commit_msg[-1]

    diff = hg_patch[i:]

    if author:
        # XXX ensure this has the Foo <foo@bar.com> form.
        # XXX Do I have to worry about text encoding here?
        print('From: %s' % author)
    else:
        print('From: unknown@unknown.com')
    if date:
        print('Date: %s' % date)
    if commit_msg:
        print('Subject: %s' % commit_msg[0])

    print()
    print('\n'.join(commit_msg[1:]))
    print()
    print('\n'.join(diff))

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == '--test':
        import doctest
        doctest.testmod()
        sys.exit(0)

    if len(sys.argv) == 1:
        file = sys.stdin
    elif len(sys.argv) == 2:
        file = open(sys.argv[1], 'r')
    else:
        print('Error: Specify one file, or pipe input on stdin.')
        sys.exit(1)

    hg_patch_to_git_patch(file)