Repository: pre-commit/pre-commit

Issue:
FileExistsError : [WinError 183] Cannot create a file when that file already exists
version : 1.15.2
OS : Windows 10

```console
$ pre-commit install

An unexpected error has occurred: FileExistsError: [WinError 183] Cannot create a file when that file already exists: '.git\\hooks\\pre-commit' -> '.git\\hooks\\pre-commit.legacy'
```

when i tried second times this was the error.


Discussion:
Interesting, can you produce a full trace? (should be in the pre-commit log mentioned in the error output) 
nevermind! I was able to reproduce this by doing the following:

```bash
echo -e '#!/usr/bin/env bash\necho hi' > .git/hook/pre-commit
pre-commit install
echo -e '#!/usr/bin/env bash\necho hi' > .git/hook/pre-commit
pre-commit install
```

When I ran the last `pre-commit install` I ended up with this output:

```console
$ pre-commit install
An unexpected error has occurred: FileExistsError: [WinError 183] Canno
t create a file when that file already exists: '.git\\hooks\\pre-commit
' -> '.git\\hooks\\pre-commit.legacy'
Check the log at C:\Users\Anthony/.cache\pre-commit\pre-commit.log
```

And here's the contents of the stacktrace in the log


```python
An unexpected error has occurred: FileExistsError: [WinError 183] Cannot create a file when that file already exists: '.git\\hooks\\pre-commit' -> '.git\\hooks\\pre-commit.legacy'
Traceback (most recent call last):
  File "c:\users\anthony\appdata\local\temp\t\pyupgrade\venv\lib\site-packages\pre_commit\error_handler.py", line 46, in error_handler
    yield
  File "c:\users\anthony\appdata\local\temp\t\pyupgrade\venv\lib\site-packages\pre_commit\main.py", line 271, in main
    skip_on_missing_conf=args.allow_missing_config,
  File "c:\users\anthony\appdata\local\temp\t\pyupgrade\venv\lib\site-packages\pre_commit\commands\install_uninstall.py", line 87, in install
    os.rename(hook_path, legacy_path)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: '.git\\hooks\\pre-commit' -> '.git\\hooks\\pre-commit.legacy'
```

Resolving patch:
diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py
--- a/pre_commit/commands/install_uninstall.py
+++ b/pre_commit/commands/install_uninstall.py
@@ -5,6 +5,7 @@
 import itertools
 import logging
 import os.path
+import shutil
 import sys
 
 from pre_commit import git
@@ -84,7 +85,7 @@ def install(
 
     # If we have an existing hook, move it to pre-commit.legacy
     if os.path.lexists(hook_path) and not is_our_script(hook_path):
-        os.rename(hook_path, legacy_path)
+        shutil.move(hook_path, legacy_path)
 
     # If we specify overwrite, we simply delete the legacy file
     if overwrite and os.path.exists(legacy_path):


Test patch:
diff --git a/tests/commands/install_uninstall_test.py b/tests/commands/install_uninstall_test.py
--- a/tests/commands/install_uninstall_test.py
+++ b/tests/commands/install_uninstall_test.py
@@ -325,6 +325,16 @@ def test_install_existing_hooks_no_overwrite(tempdir_factory, store):
         assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
 
 
+def test_legacy_overwriting_legacy_hook(tempdir_factory, store):
+    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
+    with cwd(path):
+        _write_legacy_hook(path)
+        assert install(C.CONFIG_FILE, store) == 0
+        _write_legacy_hook(path)
+        # this previously crashed on windows.  See #1010
+        assert install(C.CONFIG_FILE, store) == 0
+
+
 def test_install_existing_hook_no_overwrite_idempotent(tempdir_factory, store):
     path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
     with cwd(path):