# Buggy code
def staged_files_only(cmd_runner):
    """Clear any unstaged changes from the git working directory inside this
    context.

    Args:
        cmd_runner - PrefixedCommandRunner
    """
    # Determine if there are unstaged files
    retcode, _, _ = cmd_runner.run(
        ["git", "diff-files", "--quiet"],
        retcode=None,
    )
    if retcode:
        patch_filename = cmd_runner.path("patch{0}".format(int(time.time())))
        logger.warning("Unstaged files detected.")
        logger.info(
            "Stashing unstaged files to {0}.".format(patch_filename),
        )
        # Save the current unstaged changes as a patch
        with open(patch_filename, "w") as patch_file:
            cmd_runner.run(["git", "diff", "--binary"], stdout=patch_file)

        # Clear the working directory of unstaged changes
        cmd_runner.run(["git", "checkout", "--", "."])
        try:
            yield
        finally:
            # Try to apply the patch we saved
            try:
                cmd_runner.run(["git", "apply", patch_filename])
            except CalledProcessError:
                logger.warning(
                    "Stashed changes conflicted with hook auto-fixes... "
                    "Rolling back fixes..."
                )
                # We failed to apply the patch, presumably due to fixes made
                # by hooks.
                # Roll back the changes made by hooks.
                cmd_runner.run(["git", "checkout", "--", "."])
                cmd_runner.run(["git", "apply", patch_filename])
            logger.info("Restored changes from {0}.".format(patch_filename))
    else:
        # There weren't any staged files so we don't need to do anything
        # special
        yield


# Traceback (pre_commit.prefixed_command_runner.CalledProcessError)
$ pre-commit
[WARNING] Unstaged files detected.
Stashing unstaged files to /home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090.
Trim Trailing Whitespace............................................Passed
Fix End of Files....................................................Passed
Check Yaml..........................................................Passed
Debug Statements (Python)...........................................Passed
Tests should end in _test.py........................................Passed
Pyflakes............................................................Passed
Validate Pre-Commit Config..........................................Passed
Validate Pre-Commit Manifest........................................Passed
[WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...
Traceback (most recent call last):
File "/home/anthony/workspace/pre-commit/venv-pre_commit/bin/pre-commit", line 9, in <module>
load_entry_point('pre-commit==0.0.0', 'console_scripts', 'pre-commit')()
File "/home/anthony/workspace/pre-commit/pre_commit/util.py", line 52, in wrapper
return func(argv)
File "/home/anthony/workspace/pre-commit/pre_commit/run.py", line 143, in run
return _run(runner, args)
File "/home/anthony/workspace/pre-commit/pre_commit/run.py", line 95, in _run
return run_hooks(runner, args)
File "/usr/lib/python2.7/contextlib.py", line 24, in __exit__
self.gen.next()
File "/home/anthony/workspace/pre-commit/pre_commit/staged_files_only.py", line 51, in staged_files_only
cmd_runner.run(['git', 'apply', patch_filename])
File "/home/anthony/workspace/pre-commit/pre_commit/prefixed_command_runner.py", line 67, in run
returncode, replaced_cmd, retcode, output=(stdout, stderr),
pre_commit.prefixed_command_runner.CalledProcessError: Command: ['git', 'apply', '/home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090']
Return code: 128
Expected return code: 0
Output: ('', 'fatal: unrecognized input\n')
$ git status
# On branch rebuild_venv
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitignore
#   modified:   Makefile
#

# Fixed code
def staged_files_only(cmd_runner):
    """Clear any unstaged changes from the git working directory inside this
    context.

    Args:
        cmd_runner - PrefixedCommandRunner
    """
    # Determine if there are unstaged files
    retcode, diff_stdout, _ = cmd_runner.run(
        ["git", "diff", "--ignore-submodules", "--binary", "--exit-code"],
        retcode=None,
    )
    if retcode and diff_stdout.strip():
        patch_filename = cmd_runner.path("patch{0}".format(int(time.time())))
        logger.warning("Unstaged files detected.")
        logger.info(
            "Stashing unstaged files to {0}.".format(patch_filename),
        )
        # Save the current unstaged changes as a patch
        with open(patch_filename, "w") as patch_file:
            patch_file.write(diff_stdout)

        # Clear the working directory of unstaged changes
        cmd_runner.run(["git", "checkout", "--", "."])
        try:
            yield
        finally:
            # Try to apply the patch we saved
            try:
                cmd_runner.run(["git", "apply", patch_filename])
            except CalledProcessError:
                logger.warning(
                    "Stashed changes conflicted with hook auto-fixes... "
                    "Rolling back fixes..."
                )
                # We failed to apply the patch, presumably due to fixes made
                # by hooks.
                # Roll back the changes made by hooks.
                cmd_runner.run(["git", "checkout", "--", "."])
                cmd_runner.run(["git", "apply", patch_filename])
            logger.info("Restored changes from {0}.".format(patch_filename))
    else:
        # There weren't any staged files so we don't need to do anything
        # special
        yield