Permalink
Browse files

Reworking git-patch-to-hg-patch so it doesn't wrap lines unnecessaril…

…y. I hope this doesn't break things.
  • Loading branch information...
1 parent f608f18 commit 9fdbdac947ff6b5a0ba287077b0950c8eec42105 @jlebar committed Jun 20, 2012
Showing with 71 additions and 29 deletions.
  1. +67 −29 git-patch-to-hg-patch
  2. +4 −0 test.sh
View
@@ -1,32 +1,72 @@
#!/usr/bin/python
-"""Git format-patch to hg importable patch.
+r"""Git format-patch to hg importable patch.
+
+(Who knew this was so complicated?)
+
+>>> process(StringIO('From 3ce1ccc06 Mon Sep 17 00:00:00 2001\nFrom: fromuser\nSubject: subject\n\nRest of patch.\nMore patch.\n'))
+'# HG changeset patch\n# User fromuser\n\nsubject\n\nRest of patch.\nMore patch.\n'
+
+>>> process(StringIO('From: fromuser\nSubject: A very long subject line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi faucibus, arcu sit amet\n\nRest of patch.\nMore patch.\n'))
+'# HG changeset patch\n# User fromuser\n\nA very long subject line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi faucibus, arcu sit amet\n\nRest of patch.\nMore patch.\n'
+
+>>> process(StringIO('From: f\nSubject: =?UTF-8?q?Bug=20655877=20-=20Dont=20treat=20SVG=20text=20frames=20?= =?UTF-8?q?as=20being=20positioned.=20r=3D=3F?=\n\nPatch.'))
+'# HG changeset patch\n# User f\n\nBug 655877 - Dont treat SVG text frames as being positioned. r=?\n\nPatch.'
"""
# Original author: bholley
import sys
import re
import fileinput
-from email.header import Header, decode_header
-
-def process(lines):
-
- # Discard the first line.
- lines.pop(0);
-
- # Read the second line, and extract the author.
- author = re.sub(r'^From: (.*)$', r'# User \1', lines.pop(0))
-
- # Discard the third line.
- lines.pop(0)
-
- # Read the subject line, filtering out the gunk and unwrapping.
- subject = re.sub(r'^Subject: (.*)', r'\1', lines.pop(0))
- nextline = lines.pop(0)
- while nextline[0] == ' ':
- subject = subject.rstrip('\n') + nextline
- nextline = lines.pop(0)
+import email, email.parser, email.header
+import math
+from cStringIO import StringIO
+from itertools import takewhile
+
+def decode_header(hdr_string):
+ rv = ''
+ hdr = email.header.Header(hdr_string, maxlinelen=float('inf'))
+ for (part, encoding) in email.header.decode_header(hdr):
+ if encoding is None:
+ rv += part
+ else:
+ rv += part.decode(encoding).encode('utf-8')
+ return rv
+
+def clean_header(hdr_string):
+ r"""Transform a header split over many lines into a header split only where
+ linebreaks are intended. This is important because hg cares about the first
+ line of the commit message.
+
+ Also clean up weird encoding crap.
+
+ >>> clean_header('Foo\n bar\n baz')
+ 'Foo bar baz'
+ >>> clean_header('Foo\n bar\nSpam\nEggs')
+ 'Foo bar\nSpam\nEggs'
+ """
+
+ lines = []
+ curline = ''
+ for line in decode_header(hdr_string).split('\n'):
+ if not line.startswith(' '):
+ lines.append(curline)
+ curline = ''
+ curline += line
+ lines.append(curline)
+ return '\n'.join(lines[1:])
+
+def process(git_patch_file):
+ parser = email.parser.Parser()
+ msg = parser.parse(git_patch_file)
+
+ return '\n'.join(['# HG changeset patch',
+ '# User ' + clean_header(msg['From']),
+ '',
+ clean_header(msg['subject']),
+ '',
+ msg.get_payload()])
# Decode the header into a UTF-8 string, in case it uses MIME encoded words
encoded_subject = Header(subject)
@@ -41,19 +81,18 @@ def process(lines):
subject = re.sub(r'\s?v\d\d?', '', subject)
# Write the header.
- lines.insert(0, '\n')
- lines.insert(0, subject)
- lines.insert(0, '\n')
- lines.insert(0, author)
- lines.insert(0, '# HG changeset patch\n')
+ return ['# HG changeset patch\n', author, '\n', subject, '\n'] + list(iterlines)
if __name__ == "__main__":
+ if len(sys.argv) > 1 and sys.argv[1] == '--test':
+ import doctest
+ doctest.testmod()
+ sys.exit(0)
# If there were no arguments, do stdin->stdout.
filelist = sys.argv[1:]
if not filelist:
- lines = sys.stdin.readlines()
- process(lines)
+ lines = process(sys.stdin)
sys.stdout.writelines(lines)
sys.exit(0)
@@ -62,11 +101,10 @@ if __name__ == "__main__":
# Read the lines.
f = open(filename, 'r')
- lines = f.readlines()
+ lines = process(f)
f.close()
# Process.
- process(lines)
# Write them back to the same file.
f = open(filename, 'w')
View
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+./git-patch-to-hg-patch --test
+echo "Tests complete."

0 comments on commit 9fdbdac

Please sign in to comment.