prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Stashed changes lost if hook fails
  I've run into this particular (in my eyes, critical) bug.
  If I want to do a partial commit, e.g. I have 2 files but I only add 1 file to the staging area and the staged file will cause a hook to fail, I loose the changes in the 2nd file because pre-commit fails to reroll the patch it stashed before running.
  
  Here's my terminal log and the steps to reproduce:
  ## Version
  
  $ pre-commit -V
  pre-commit 0.3.0
  ## Commands to reproduce
  
  ```
  $ cat unstaged.py
  """I am unstaged"""
  $ echo "'''I am unstaged, but I have changes'''" > unstaged.py
  $ echo "x = 'This is the loooooooooooooooooooooooooooooooooooongest liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiine eveeeeeeeeer'" > foo.py 
  $ git status
  On branch master
  Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)
  
      modified:   unstaged.py
      modified:   foo.py
  
  no changes added to commit (use "git add" and/or "git commit -a")
  $ git add foo.py 
  $ git commit -m "Adding a long line"
  [WARNING] Unstaged files detected.
  [INFO] Stashing unstaged files to /home/k/.pre-commit/patch1412683352.
  Flake8...............................................Failed
  hookid: flake8
  
  foo.py:1:80: E501 line too long (112 > 79 characters)
  
  [WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...
  An unexpected error has occurred: CalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']
  Return code: 128
  Expected return code: 0
  Output: (u'', u'fatal: unrecognized input\n')
  
  Check the log at ~/.pre-commit/pre-commit.log
  $ git status
  On branch master
  Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)
  
      modified:   foo.py
  
  $ echo "x = 'This is a shorter line, its better'" > foo.py
  $ git status
  On branch master
  Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)
  
      modified:   foo.py
  
  Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)
  
      modified:   foo.py
  
  $ git add foo.py 
  $ git commit -m "Fixed the error I got from the flake8 hook"
  Flake8...............................................Passed
  [master 78568e8] Fixed the error I got from the flake8 hook
   1 file changed, 1 insertion(+), 1 deletion(-)
  $ git status
  On branch master
  nothing to commit, working directory clean
  $ cat unstaged.py
  """I am unstaged"""
  ```
  ## Log
  
  ```
  $ cat ~/.pre-commit/pre-commit.log
  Traceback (most recent call last):
    File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/error_handler.py", line 34, in error_handler
      yield
    File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/main.py", line 108, in main
      return run(runner, args)
    File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/commands/run.py", line 151, in run
      return _run_hooks(runner, args, write=write, environ=environ)
    File "/usr/lib/python2.7/contextlib.py", line 24, in __exit__
      self.gen.next()
    File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/staged_files_only.py", line 55, in staged_files_only
      cmd_runner.run(['git', 'apply', patch_filename])
    File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/prefixed_command_runner.py", line 82, in run
      returncode, replaced_cmd, retcode, output=(stdout, stderr),
  CalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']
  Return code: 128
  Expected return code: 0
  Output: (u'', u'fatal: unrecognized input\n')
  ```
  ## .pre-commit-config.yaml
  
  ```
  $ cat .pre-commit-config.yaml 
  - repo: git@github.com:pre-commit/pre-commit-hooks
    sha: 6343700aa063fe30acc319d2dc84353a35a3d6d0
    hooks:
    - id: flake8
      args: ['--ignore=E712,F821']
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pre_commit/staged_files_only.py`
  Content:
  ```
  1 from __future__ import unicode_literals
  2 
  3 import contextlib
  4 import io
  5 import logging
  6 import time
  7 
  8 from pre_commit.util import CalledProcessError
  9 
  10 
  11 logger = logging.getLogger('pre_commit')
  12 
  13 
  14 @contextlib.contextmanager
  15 def staged_files_only(cmd_runner):
  16     """Clear any unstaged changes from the git working directory inside this
  17     context.
  18 
  19     Args:
  20         cmd_runner - PrefixedCommandRunner
  21     """
  22     # Determine if there are unstaged files
  23     retcode, diff_stdout_binary, _ = cmd_runner.run(
  24         ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],
  25         retcode=None,
  26         encoding=None,
  27     )
  28     if retcode and diff_stdout_binary.strip():
  29         patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))
  30         logger.warning('Unstaged files detected.')
  31         logger.info(
  32             'Stashing unstaged files to {0}.'.format(patch_filename),
  33         )
  34         # Save the current unstaged changes as a patch
  35         with io.open(patch_filename, 'wb') as patch_file:
  36             patch_file.write(diff_stdout_binary)
  37 
  38         # Clear the working directory of unstaged changes
  39         cmd_runner.run(['git', 'checkout', '--', '.'])
  40         try:
  41             yield
  42         finally:
  43             # Try to apply the patch we saved
  44             try:
  45                 cmd_runner.run(['git', 'apply', patch_filename])
  46             except CalledProcessError:
  47                 logger.warning(
  48                     'Stashed changes conflicted with hook auto-fixes... '
  49                     'Rolling back fixes...'
  50                 )
  51                 # We failed to apply the patch, presumably due to fixes made
  52                 # by hooks.
  53                 # Roll back the changes made by hooks.
  54                 cmd_runner.run(['git', 'checkout', '--', '.'])
  55                 cmd_runner.run(['git', 'apply', patch_filename])
  56             logger.info('Restored changes from {0}.'.format(patch_filename))
  57     else:
  58         # There weren't any staged files so we don't need to do anything
  59         # special
  60         yield
  61
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/pre_commit/staged_files_only.py b/pre_commit/staged_files_only.py
  --- a/pre_commit/staged_files_only.py
  +++ b/pre_commit/staged_files_only.py
  @@ -21,7 +21,10 @@
       """
       # Determine if there are unstaged files
       retcode, diff_stdout_binary, _ = cmd_runner.run(
  -        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],
  +        [
  +            'git', 'diff', '--ignore-submodules', '--binary', '--exit-code',
  +            '--no-color',
  +        ],
           retcode=None,
           encoding=None,
       )
  
verification_info: {"golden_diff": "diff --git a/pre_commit/staged_files_only.py b/pre_commit/staged_files_only.py\n--- a/pre_commit/staged_files_only.py\n+++ b/pre_commit/staged_files_only.py\n@@ -21,7 +21,10 @@\n     \"\"\"\n     # Determine if there are unstaged files\n     retcode, diff_stdout_binary, _ = cmd_runner.run(\n-        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],\n+        [\n+            'git', 'diff', '--ignore-submodules', '--binary', '--exit-code',\n+            '--no-color',\n+        ],\n         retcode=None,\n         encoding=None,\n     )\n", "issue": "Stashed changes lost if hook fails\nI've run into this particular (in my eyes, critical) bug.\nIf I want to do a partial commit, e.g. I have 2 files but I only add 1 file to the staging area and the staged file will cause a hook to fail, I loose the changes in the 2nd file because pre-commit fails to reroll the patch it stashed before running.\n\nHere's my terminal log and the steps to reproduce:\n## Version\n\n$ pre-commit -V\npre-commit 0.3.0\n## Commands to reproduce\n\n```\n$ cat unstaged.py\n\"\"\"I am unstaged\"\"\"\n$ echo \"'''I am unstaged, but I have changes'''\" > unstaged.py\n$ echo \"x = 'This is the loooooooooooooooooooooooooooooooooooongest liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiine eveeeeeeeeer'\" > foo.py \n$ git status\nOn branch master\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n    modified:   unstaged.py\n    modified:   foo.py\n\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\n$ git add foo.py \n$ git commit -m \"Adding a long line\"\n[WARNING] Unstaged files detected.\n[INFO] Stashing unstaged files to /home/k/.pre-commit/patch1412683352.\nFlake8...............................................Failed\nhookid: flake8\n\nfoo.py:1:80: E501 line too long (112 > 79 characters)\n\n[WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...\nAn unexpected error has occurred: CalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']\nReturn code: 128\nExpected return code: 0\nOutput: (u'', u'fatal: unrecognized input\\n')\n\nCheck the log at ~/.pre-commit/pre-commit.log\n$ git status\nOn branch master\nChanges to be committed:\n  (use \"git reset HEAD <file>...\" to unstage)\n\n    modified:   foo.py\n\n$ echo \"x = 'This is a shorter line, its better'\" > foo.py\n$ git status\nOn branch master\nChanges to be committed:\n  (use \"git reset HEAD <file>...\" to unstage)\n\n    modified:   foo.py\n\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n    modified:   foo.py\n\n$ git add foo.py \n$ git commit -m \"Fixed the error I got from the flake8 hook\"\nFlake8...............................................Passed\n[master 78568e8] Fixed the error I got from the flake8 hook\n 1 file changed, 1 insertion(+), 1 deletion(-)\n$ git status\nOn branch master\nnothing to commit, working directory clean\n$ cat unstaged.py\n\"\"\"I am unstaged\"\"\"\n```\n## Log\n\n```\n$ cat ~/.pre-commit/pre-commit.log\nTraceback (most recent call last):\n  File \"/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/error_handler.py\", line 34, in error_handler\n    yield\n  File \"/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/main.py\", line 108, in main\n    return run(runner, args)\n  File \"/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/commands/run.py\", line 151, in run\n    return _run_hooks(runner, args, write=write, environ=environ)\n  File \"/usr/lib/python2.7/contextlib.py\", line 24, in __exit__\n    self.gen.next()\n  File \"/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/staged_files_only.py\", line 55, in staged_files_only\n    cmd_runner.run(['git', 'apply', patch_filename])\n  File \"/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/prefixed_command_runner.py\", line 82, in run\n    returncode, replaced_cmd, retcode, output=(stdout, stderr),\nCalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']\nReturn code: 128\nExpected return code: 0\nOutput: (u'', u'fatal: unrecognized input\\n')\n```\n## .pre-commit-config.yaml\n\n```\n$ cat .pre-commit-config.yaml \n- repo: git@github.com:pre-commit/pre-commit-hooks\n  sha: 6343700aa063fe30acc319d2dc84353a35a3d6d0\n  hooks:\n  - id: flake8\n    args: ['--ignore=E712,F821']\n```\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport time\n\nfrom pre_commit.util import CalledProcessError\n\n\nlogger = logging.getLogger('pre_commit')\n\n\n@contextlib.contextmanager\ndef staged_files_only(cmd_runner):\n    \"\"\"Clear any unstaged changes from the git working directory inside this\n    context.\n\n    Args:\n        cmd_runner - PrefixedCommandRunner\n    \"\"\"\n    # Determine if there are unstaged files\n    retcode, diff_stdout_binary, _ = cmd_runner.run(\n        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],\n        retcode=None,\n        encoding=None,\n    )\n    if retcode and diff_stdout_binary.strip():\n        patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))\n        logger.warning('Unstaged files detected.')\n        logger.info(\n            'Stashing unstaged files to {0}.'.format(patch_filename),\n        )\n        # Save the current unstaged changes as a patch\n        with io.open(patch_filename, 'wb') as patch_file:\n            patch_file.write(diff_stdout_binary)\n\n        # Clear the working directory of unstaged changes\n        cmd_runner.run(['git', 'checkout', '--', '.'])\n        try:\n            yield\n        finally:\n            # Try to apply the patch we saved\n            try:\n                cmd_runner.run(['git', 'apply', patch_filename])\n            except CalledProcessError:\n                logger.warning(\n                    'Stashed changes conflicted with hook auto-fixes... '\n                    'Rolling back fixes...'\n                )\n                # We failed to apply the patch, presumably due to fixes made\n                # by hooks.\n                # Roll back the changes made by hooks.\n                cmd_runner.run(['git', 'checkout', '--', '.'])\n                cmd_runner.run(['git', 'apply', patch_filename])\n            logger.info('Restored changes from {0}.'.format(patch_filename))\n    else:\n        # There weren't any staged files so we don't need to do anything\n        # special\n        yield\n", "path": "pre_commit/staged_files_only.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport time\n\nfrom pre_commit.util import CalledProcessError\n\n\nlogger = logging.getLogger('pre_commit')\n\n\n@contextlib.contextmanager\ndef staged_files_only(cmd_runner):\n    \"\"\"Clear any unstaged changes from the git working directory inside this\n    context.\n\n    Args:\n        cmd_runner - PrefixedCommandRunner\n    \"\"\"\n    # Determine if there are unstaged files\n    retcode, diff_stdout_binary, _ = cmd_runner.run(\n        [\n            'git', 'diff', '--ignore-submodules', '--binary', '--exit-code',\n            '--no-color',\n        ],\n        retcode=None,\n        encoding=None,\n    )\n    if retcode and diff_stdout_binary.strip():\n        patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))\n        logger.warning('Unstaged files detected.')\n        logger.info(\n            'Stashing unstaged files to {0}.'.format(patch_filename),\n        )\n        # Save the current unstaged changes as a patch\n        with io.open(patch_filename, 'wb') as patch_file:\n            patch_file.write(diff_stdout_binary)\n\n        # Clear the working directory of unstaged changes\n        cmd_runner.run(['git', 'checkout', '--', '.'])\n        try:\n            yield\n        finally:\n            # Try to apply the patch we saved\n            try:\n                cmd_runner.run(['git', 'apply', patch_filename])\n            except CalledProcessError:\n                logger.warning(\n                    'Stashed changes conflicted with hook auto-fixes... '\n                    'Rolling back fixes...'\n                )\n                # We failed to apply the patch, presumably due to fixes made\n                # by hooks.\n                # Roll back the changes made by hooks.\n                cmd_runner.run(['git', 'checkout', '--', '.'])\n                cmd_runner.run(['git', 'apply', patch_filename])\n            logger.info('Restored changes from {0}.'.format(patch_filename))\n    else:\n        # There weren't any staged files so we don't need to do anything\n        # special\n        yield\n", "path": "pre_commit/staged_files_only.py"}]}