Added end of file fixer hook.
diff --git a/manifest.yaml b/manifest.yaml
index 00b48d9..8686643 100644
--- a/manifest.yaml
+++ b/manifest.yaml
@@ -19,3 +19,8 @@
     description: This verifies that test files are named correctly
     entry: name-tests-test
     language: python
+-   id: end-of-file-fixer
+    name: Fix End of Files
+    description: Ensures that a file is either empty, or ends with one newline.
+    entry: end-of-file-fixer
+    language: python
diff --git a/pre_commit_hooks/end_of_file_fixer.py b/pre_commit_hooks/end_of_file_fixer.py
new file mode 100644
index 0000000..b585ce3
--- /dev/null
+++ b/pre_commit_hooks/end_of_file_fixer.py
@@ -0,0 +1,70 @@
+
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import argparse
+import os
+import sys
+
+from pre_commit_hooks.util import entry
+
+
+def fix_file(file_obj):
+    # Test for newline at end of file
+    # Empty files will throw IOError here
+    try:
+        file_obj.seek(-1, os.SEEK_END)
+    except IOError:
+        return 0
+    last_character = file_obj.read(1)
+    # last_character will be '' for an empty file
+    if last_character != '\n' and last_character != '':
+        file_obj.write('\n')
+        return 1
+
+    while last_character == '\n':
+        # Deal with the beginning of the file
+        if file_obj.tell() == 1:
+            # If we've reached the beginning of the file and it is all
+            # linebreaks then we can make this file empty
+            file_obj.seek(0)
+            file_obj.truncate()
+            return 1
+
+        # Go back two bytes and read a character
+        file_obj.seek(-2, os.SEEK_CUR)
+        last_character = file_obj.read(1)
+
+    # Our current position is at the end of the file just before any amount of
+    # newlines.  If we read two characters and get two newlines back we know
+    # there are extraneous newlines at the ned of the file.  Then backtrack and
+    # trim the end off.
+    if len(file_obj.read(2)) == 2:
+        file_obj.seek(-1, os.SEEK_CUR)
+        file_obj.truncate()
+        return 1
+
+    return 0
+
+
+@entry
+def end_of_file_fixer(argv):
+    parser = argparse.ArgumentParser()
+    parser.add_argument('filenames', nargs='*', help='Filenames to fix')
+    args = parser.parse_args(argv)
+
+    retv = 0
+
+    for filename in args.filenames:
+        # Read as binary so we can read byte-by-byte
+        with open(filename, 'rb+') as file_obj:
+            ret_for_file = fix_file(file_obj)
+            if ret_for_file:
+                print('Fixing {0}'.format(filename))
+            retv |= ret_for_file
+
+    return retv
+
+
+if __name__ == '__main__':
+    sys.exit(end_of_file_fixer())
diff --git a/setup.py b/setup.py
index 42afa6a..96d8d3a 100644
--- a/setup.py
+++ b/setup.py
@@ -16,6 +16,7 @@
             'debug-statement-hook = pre_commit_hooks.debug_statement_hook:debug_statement_hook',
             'trailing-whitespace-fixer = pre_commit_hooks.trailing_whitespace_fixer:fix_trailing_whitespace',
             'name-tests-test = pre_commit_hooks.tests_should_end_in_test:validate_files',
+            'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer',
         ],
     },
 )
diff --git a/tests/end_of_file_fixer_test.py b/tests/end_of_file_fixer_test.py
new file mode 100644
index 0000000..444836e
--- /dev/null
+++ b/tests/end_of_file_fixer_test.py
@@ -0,0 +1,42 @@
+
+import cStringIO
+import os.path
+import pytest
+
+from pre_commit_hooks.end_of_file_fixer import end_of_file_fixer
+from pre_commit_hooks.end_of_file_fixer import fix_file
+
+
+# Input, expected return value, expected output
+TESTS = (
+    ('foo\n', 0, 'foo\n'),
+    ('', 0, ''),
+    ('\n\n', 1, ''),
+    ('\n\n\n\n', 1, ''),
+    ('foo', 1, 'foo\n'),
+    ('foo\n\n\n', 1, 'foo\n'),
+    ('\xe2\x98\x83', 1, '\xe2\x98\x83\n'),
+)
+
+
+@pytest.mark.parametrize(('input', 'expected_retval', 'output'), TESTS)
+def test_fix_file(input, expected_retval, output):
+    file_obj = cStringIO.StringIO()
+    file_obj.write(input)
+    ret = fix_file(file_obj)
+    assert file_obj.getvalue() == output
+    assert ret == expected_retval
+
+
+@pytest.mark.parametrize(('input', 'expected_retval', 'output'), TESTS)
+def test_integration(input, expected_retval, output, tmpdir):
+    file_path = os.path.join(tmpdir.strpath, 'file.txt')
+
+    with open(file_path, 'w') as file_obj:
+        file_obj.write(input)
+
+    ret = end_of_file_fixer([file_path])
+    file_output = open(file_path, 'r').read()
+
+    assert file_output == output
+    assert ret == expected_retval