We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
running `pre-commit autoupdate` fails because tip of HEAD is missing hook
Hello 👋 
I'm setting up `pre-commit` on a project and came across an issue when adding hook `destroyed-symlinks`. The error message suggested running `pre-commit autoupdate`. I ran that and saw that it cannot update because the tip of HEAD is missing that hook. I'm not sure what that means so posting here.

```console
$ echo '    -   id: destroyed-symlinks' >> .pre-commit-config.yaml
$ git add -p !$
git add -p .pre-commit-config.yaml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index bfde4717..949f3ffc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -21,3 +21,4 @@ repos:
     -   id: check-vcs-permalinks
     -   id: check-xml
     -   id: debug-statements
+    -   id: destroyed-symlinks
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y

$ git commit -m 'new hook destroyed-symlinks'
[ERROR] `destroyed-symlinks` is not present in repository https://github.com/pre-commit/pre-commit-hooks.  Typo? Perhaps it is introduced in a newer version?  Often `pre-commit autoupdate` fixes this.
$ git status
On branch pre-commit
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   .pre-commit-config.yaml

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        tests/__init__.py

$ pre-commit autoupdate
Updating https://github.com/pre-commit/pre-commit-hooks ... [INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
Cannot update because the tip of HEAD is missing these hooks:
destroyed-symlinks
$ git checkout .
Updated 0 paths from the index
$ pre-commit autoupdate
Updating https://github.com/pre-commit/pre-commit-hooks ... Cannot update because the tip of HEAD is missing these hooks:
destroyed-symlinks
$ pre-commit --version
pre-commit 2.9.0
```

--- 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/commands/autoupdate.py`
Content:
```
1 import os.path
2 import re
3 from typing import Any
4 from typing import Dict
5 from typing import List
6 from typing import NamedTuple
7 from typing import Optional
8 from typing import Sequence
9 from typing import Tuple
10 
11 import pre_commit.constants as C
12 from pre_commit import git
13 from pre_commit import output
14 from pre_commit.clientlib import InvalidManifestError
15 from pre_commit.clientlib import load_config
16 from pre_commit.clientlib import load_manifest
17 from pre_commit.clientlib import LOCAL
18 from pre_commit.clientlib import META
19 from pre_commit.commands.migrate_config import migrate_config
20 from pre_commit.store import Store
21 from pre_commit.util import CalledProcessError
22 from pre_commit.util import cmd_output
23 from pre_commit.util import cmd_output_b
24 from pre_commit.util import tmpdir
25 from pre_commit.util import yaml_dump
26 from pre_commit.util import yaml_load
27 
28 
29 class RevInfo(NamedTuple):
30     repo: str
31     rev: str
32     frozen: Optional[str]
33 
34     @classmethod
35     def from_config(cls, config: Dict[str, Any]) -> 'RevInfo':
36         return cls(config['repo'], config['rev'], None)
37 
38     def update(self, tags_only: bool, freeze: bool) -> 'RevInfo':
39         if tags_only:
40             tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--abbrev=0')
41         else:
42             tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--exact')
43 
44         with tmpdir() as tmp:
45             git.init_repo(tmp, self.repo)
46             cmd_output_b('git', 'fetch', 'origin', 'HEAD', '--tags', cwd=tmp)
47 
48             try:
49                 rev = cmd_output(*tag_cmd, cwd=tmp)[1].strip()
50             except CalledProcessError:
51                 cmd = ('git', 'rev-parse', 'FETCH_HEAD')
52                 rev = cmd_output(*cmd, cwd=tmp)[1].strip()
53 
54             frozen = None
55             if freeze:
56                 exact = cmd_output('git', 'rev-parse', rev, cwd=tmp)[1].strip()
57                 if exact != rev:
58                     rev, frozen = exact, rev
59         return self._replace(rev=rev, frozen=frozen)
60 
61 
62 class RepositoryCannotBeUpdatedError(RuntimeError):
63     pass
64 
65 
66 def _check_hooks_still_exist_at_rev(
67         repo_config: Dict[str, Any],
68         info: RevInfo,
69         store: Store,
70 ) -> None:
71     try:
72         path = store.clone(repo_config['repo'], info.rev)
73         manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
74     except InvalidManifestError as e:
75         raise RepositoryCannotBeUpdatedError(str(e))
76 
77     # See if any of our hooks were deleted with the new commits
78     hooks = {hook['id'] for hook in repo_config['hooks']}
79     hooks_missing = hooks - {hook['id'] for hook in manifest}
80     if hooks_missing:
81         raise RepositoryCannotBeUpdatedError(
82             f'Cannot update because the tip of HEAD is missing these hooks:\n'
83             f'{", ".join(sorted(hooks_missing))}',
84         )
85 
86 
87 REV_LINE_RE = re.compile(r'^(\s+)rev:(\s*)([\'"]?)([^\s#]+)(.*)(\r?\n)$')
88 
89 
90 def _original_lines(
91         path: str,
92         rev_infos: List[Optional[RevInfo]],
93         retry: bool = False,
94 ) -> Tuple[List[str], List[int]]:
95     """detect `rev:` lines or reformat the file"""
96     with open(path, newline='') as f:
97         original = f.read()
98 
99     lines = original.splitlines(True)
100     idxs = [i for i, line in enumerate(lines) if REV_LINE_RE.match(line)]
101     if len(idxs) == len(rev_infos):
102         return lines, idxs
103     elif retry:
104         raise AssertionError('could not find rev lines')
105     else:
106         with open(path, 'w') as f:
107             f.write(yaml_dump(yaml_load(original)))
108         return _original_lines(path, rev_infos, retry=True)
109 
110 
111 def _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:
112     lines, idxs = _original_lines(path, rev_infos)
113 
114     for idx, rev_info in zip(idxs, rev_infos):
115         if rev_info is None:
116             continue
117         match = REV_LINE_RE.match(lines[idx])
118         assert match is not None
119         new_rev_s = yaml_dump({'rev': rev_info.rev}, default_style=match[3])
120         new_rev = new_rev_s.split(':', 1)[1].strip()
121         if rev_info.frozen is not None:
122             comment = f'  # frozen: {rev_info.frozen}'
123         elif match[5].strip().startswith('# frozen:'):
124             comment = ''
125         else:
126             comment = match[5]
127         lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[6]}'
128 
129     with open(path, 'w', newline='') as f:
130         f.write(''.join(lines))
131 
132 
133 def autoupdate(
134         config_file: str,
135         store: Store,
136         tags_only: bool,
137         freeze: bool,
138         repos: Sequence[str] = (),
139 ) -> int:
140     """Auto-update the pre-commit config to the latest versions of repos."""
141     migrate_config(config_file, quiet=True)
142     retv = 0
143     rev_infos: List[Optional[RevInfo]] = []
144     changed = False
145 
146     config = load_config(config_file)
147     for repo_config in config['repos']:
148         if repo_config['repo'] in {LOCAL, META}:
149             continue
150 
151         info = RevInfo.from_config(repo_config)
152         if repos and info.repo not in repos:
153             rev_infos.append(None)
154             continue
155 
156         output.write(f'Updating {info.repo} ... ')
157         new_info = info.update(tags_only=tags_only, freeze=freeze)
158         try:
159             _check_hooks_still_exist_at_rev(repo_config, new_info, store)
160         except RepositoryCannotBeUpdatedError as error:
161             output.write_line(error.args[0])
162             rev_infos.append(None)
163             retv = 1
164             continue
165 
166         if new_info.rev != info.rev:
167             changed = True
168             if new_info.frozen:
169                 updated_to = f'{new_info.frozen} (frozen)'
170             else:
171                 updated_to = new_info.rev
172             msg = f'updating {info.rev} -> {updated_to}.'
173             output.write_line(msg)
174             rev_infos.append(new_info)
175         else:
176             output.write_line('already up to date.')
177             rev_infos.append(None)
178 
179     if changed:
180         _write_new_config(config_file, rev_infos)
181 
182     return retv
183
```
--- 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()

```

diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py
--- a/pre_commit/commands/autoupdate.py
+++ b/pre_commit/commands/autoupdate.py
@@ -79,8 +79,8 @@
     hooks_missing = hooks - {hook['id'] for hook in manifest}
     if hooks_missing:
         raise RepositoryCannotBeUpdatedError(
-            f'Cannot update because the tip of HEAD is missing these hooks:\n'
-            f'{", ".join(sorted(hooks_missing))}',
+            f'Cannot update because the update target is missing these '
+            f'hooks:\n{", ".join(sorted(hooks_missing))}',
         )

{"golden_diff": "diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py\n--- a/pre_commit/commands/autoupdate.py\n+++ b/pre_commit/commands/autoupdate.py\n@@ -79,8 +79,8 @@\n     hooks_missing = hooks - {hook['id'] for hook in manifest}\n     if hooks_missing:\n         raise RepositoryCannotBeUpdatedError(\n-            f'Cannot update because the tip of HEAD is missing these hooks:\\n'\n-            f'{\", \".join(sorted(hooks_missing))}',\n+            f'Cannot update because the update target is missing these '\n+            f'hooks:\\n{\", \".join(sorted(hooks_missing))}',\n         )\n", "issue": "running `pre-commit autoupdate` fails because tip of HEAD is missing hook\nHello \ud83d\udc4b \r\nI'm setting up `pre-commit` on a project and came across an issue when adding hook `destroyed-symlinks`. The error message suggested running `pre-commit autoupdate`. I ran that and saw that it cannot update because the tip of HEAD is missing that hook. I'm not sure what that means so posting here.\r\n\r\n```console\r\n$ echo '    -   id: destroyed-symlinks' >> .pre-commit-config.yaml\r\n$ git add -p !$\r\ngit add -p .pre-commit-config.yaml\r\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\r\nindex bfde4717..949f3ffc 100644\r\n--- a/.pre-commit-config.yaml\r\n+++ b/.pre-commit-config.yaml\r\n@@ -21,3 +21,4 @@ repos:\r\n     -   id: check-vcs-permalinks\r\n     -   id: check-xml\r\n     -   id: debug-statements\r\n+    -   id: destroyed-symlinks\r\n(1/1) Stage this hunk [y,n,q,a,d,e,?]? y\r\n\r\n$ git commit -m 'new hook destroyed-symlinks'\r\n[ERROR] `destroyed-symlinks` is not present in repository https://github.com/pre-commit/pre-commit-hooks.  Typo? Perhaps it is introduced in a newer version?  Often `pre-commit autoupdate` fixes this.\r\n$ git status\r\nOn branch pre-commit\r\nChanges to be committed:\r\n  (use \"git restore --staged <file>...\" to unstage)\r\n        modified:   .pre-commit-config.yaml\r\n\r\nUntracked files:\r\n  (use \"git add <file>...\" to include in what will be committed)\r\n        tests/__init__.py\r\n\r\n$ pre-commit autoupdate\r\nUpdating https://github.com/pre-commit/pre-commit-hooks ... [INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.\r\nCannot update because the tip of HEAD is missing these hooks:\r\ndestroyed-symlinks\r\n$ git checkout .\r\nUpdated 0 paths from the index\r\n$ pre-commit autoupdate\r\nUpdating https://github.com/pre-commit/pre-commit-hooks ... Cannot update because the tip of HEAD is missing these hooks:\r\ndestroyed-symlinks\r\n$ pre-commit --version\r\npre-commit 2.9.0\r\n```\n", "before_files": [{"content": "import os.path\nimport re\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import NamedTuple\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.clientlib import InvalidManifestError\nfrom pre_commit.clientlib import load_config\nfrom pre_commit.clientlib import load_manifest\nfrom pre_commit.clientlib import LOCAL\nfrom pre_commit.clientlib import META\nfrom pre_commit.commands.migrate_config import migrate_config\nfrom pre_commit.store import Store\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cmd_output_b\nfrom pre_commit.util import tmpdir\nfrom pre_commit.util import yaml_dump\nfrom pre_commit.util import yaml_load\n\n\nclass RevInfo(NamedTuple):\n    repo: str\n    rev: str\n    frozen: Optional[str]\n\n    @classmethod\n    def from_config(cls, config: Dict[str, Any]) -> 'RevInfo':\n        return cls(config['repo'], config['rev'], None)\n\n    def update(self, tags_only: bool, freeze: bool) -> 'RevInfo':\n        if tags_only:\n            tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--abbrev=0')\n        else:\n            tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--exact')\n\n        with tmpdir() as tmp:\n            git.init_repo(tmp, self.repo)\n            cmd_output_b('git', 'fetch', 'origin', 'HEAD', '--tags', cwd=tmp)\n\n            try:\n                rev = cmd_output(*tag_cmd, cwd=tmp)[1].strip()\n            except CalledProcessError:\n                cmd = ('git', 'rev-parse', 'FETCH_HEAD')\n                rev = cmd_output(*cmd, cwd=tmp)[1].strip()\n\n            frozen = None\n            if freeze:\n                exact = cmd_output('git', 'rev-parse', rev, cwd=tmp)[1].strip()\n                if exact != rev:\n                    rev, frozen = exact, rev\n        return self._replace(rev=rev, frozen=frozen)\n\n\nclass RepositoryCannotBeUpdatedError(RuntimeError):\n    pass\n\n\ndef _check_hooks_still_exist_at_rev(\n        repo_config: Dict[str, Any],\n        info: RevInfo,\n        store: Store,\n) -> None:\n    try:\n        path = store.clone(repo_config['repo'], info.rev)\n        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))\n    except InvalidManifestError as e:\n        raise RepositoryCannotBeUpdatedError(str(e))\n\n    # See if any of our hooks were deleted with the new commits\n    hooks = {hook['id'] for hook in repo_config['hooks']}\n    hooks_missing = hooks - {hook['id'] for hook in manifest}\n    if hooks_missing:\n        raise RepositoryCannotBeUpdatedError(\n            f'Cannot update because the tip of HEAD is missing these hooks:\\n'\n            f'{\", \".join(sorted(hooks_missing))}',\n        )\n\n\nREV_LINE_RE = re.compile(r'^(\\s+)rev:(\\s*)([\\'\"]?)([^\\s#]+)(.*)(\\r?\\n)$')\n\n\ndef _original_lines(\n        path: str,\n        rev_infos: List[Optional[RevInfo]],\n        retry: bool = False,\n) -> Tuple[List[str], List[int]]:\n    \"\"\"detect `rev:` lines or reformat the file\"\"\"\n    with open(path, newline='') as f:\n        original = f.read()\n\n    lines = original.splitlines(True)\n    idxs = [i for i, line in enumerate(lines) if REV_LINE_RE.match(line)]\n    if len(idxs) == len(rev_infos):\n        return lines, idxs\n    elif retry:\n        raise AssertionError('could not find rev lines')\n    else:\n        with open(path, 'w') as f:\n            f.write(yaml_dump(yaml_load(original)))\n        return _original_lines(path, rev_infos, retry=True)\n\n\ndef _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:\n    lines, idxs = _original_lines(path, rev_infos)\n\n    for idx, rev_info in zip(idxs, rev_infos):\n        if rev_info is None:\n            continue\n        match = REV_LINE_RE.match(lines[idx])\n        assert match is not None\n        new_rev_s = yaml_dump({'rev': rev_info.rev}, default_style=match[3])\n        new_rev = new_rev_s.split(':', 1)[1].strip()\n        if rev_info.frozen is not None:\n            comment = f'  # frozen: {rev_info.frozen}'\n        elif match[5].strip().startswith('# frozen:'):\n            comment = ''\n        else:\n            comment = match[5]\n        lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[6]}'\n\n    with open(path, 'w', newline='') as f:\n        f.write(''.join(lines))\n\n\ndef autoupdate(\n        config_file: str,\n        store: Store,\n        tags_only: bool,\n        freeze: bool,\n        repos: Sequence[str] = (),\n) -> int:\n    \"\"\"Auto-update the pre-commit config to the latest versions of repos.\"\"\"\n    migrate_config(config_file, quiet=True)\n    retv = 0\n    rev_infos: List[Optional[RevInfo]] = []\n    changed = False\n\n    config = load_config(config_file)\n    for repo_config in config['repos']:\n        if repo_config['repo'] in {LOCAL, META}:\n            continue\n\n        info = RevInfo.from_config(repo_config)\n        if repos and info.repo not in repos:\n            rev_infos.append(None)\n            continue\n\n        output.write(f'Updating {info.repo} ... ')\n        new_info = info.update(tags_only=tags_only, freeze=freeze)\n        try:\n            _check_hooks_still_exist_at_rev(repo_config, new_info, store)\n        except RepositoryCannotBeUpdatedError as error:\n            output.write_line(error.args[0])\n            rev_infos.append(None)\n            retv = 1\n            continue\n\n        if new_info.rev != info.rev:\n            changed = True\n            if new_info.frozen:\n                updated_to = f'{new_info.frozen} (frozen)'\n            else:\n                updated_to = new_info.rev\n            msg = f'updating {info.rev} -> {updated_to}.'\n            output.write_line(msg)\n            rev_infos.append(new_info)\n        else:\n            output.write_line('already up to date.')\n            rev_infos.append(None)\n\n    if changed:\n        _write_new_config(config_file, rev_infos)\n\n    return retv\n", "path": "pre_commit/commands/autoupdate.py"}], "after_files": [{"content": "import os.path\nimport re\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import NamedTuple\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.clientlib import InvalidManifestError\nfrom pre_commit.clientlib import load_config\nfrom pre_commit.clientlib import load_manifest\nfrom pre_commit.clientlib import LOCAL\nfrom pre_commit.clientlib import META\nfrom pre_commit.commands.migrate_config import migrate_config\nfrom pre_commit.store import Store\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cmd_output_b\nfrom pre_commit.util import tmpdir\nfrom pre_commit.util import yaml_dump\nfrom pre_commit.util import yaml_load\n\n\nclass RevInfo(NamedTuple):\n    repo: str\n    rev: str\n    frozen: Optional[str]\n\n    @classmethod\n    def from_config(cls, config: Dict[str, Any]) -> 'RevInfo':\n        return cls(config['repo'], config['rev'], None)\n\n    def update(self, tags_only: bool, freeze: bool) -> 'RevInfo':\n        if tags_only:\n            tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--abbrev=0')\n        else:\n            tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags', '--exact')\n\n        with tmpdir() as tmp:\n            git.init_repo(tmp, self.repo)\n            cmd_output_b('git', 'fetch', 'origin', 'HEAD', '--tags', cwd=tmp)\n\n            try:\n                rev = cmd_output(*tag_cmd, cwd=tmp)[1].strip()\n            except CalledProcessError:\n                cmd = ('git', 'rev-parse', 'FETCH_HEAD')\n                rev = cmd_output(*cmd, cwd=tmp)[1].strip()\n\n            frozen = None\n            if freeze:\n                exact = cmd_output('git', 'rev-parse', rev, cwd=tmp)[1].strip()\n                if exact != rev:\n                    rev, frozen = exact, rev\n        return self._replace(rev=rev, frozen=frozen)\n\n\nclass RepositoryCannotBeUpdatedError(RuntimeError):\n    pass\n\n\ndef _check_hooks_still_exist_at_rev(\n        repo_config: Dict[str, Any],\n        info: RevInfo,\n        store: Store,\n) -> None:\n    try:\n        path = store.clone(repo_config['repo'], info.rev)\n        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))\n    except InvalidManifestError as e:\n        raise RepositoryCannotBeUpdatedError(str(e))\n\n    # See if any of our hooks were deleted with the new commits\n    hooks = {hook['id'] for hook in repo_config['hooks']}\n    hooks_missing = hooks - {hook['id'] for hook in manifest}\n    if hooks_missing:\n        raise RepositoryCannotBeUpdatedError(\n            f'Cannot update because the update target is missing these '\n            f'hooks:\\n{\", \".join(sorted(hooks_missing))}',\n        )\n\n\nREV_LINE_RE = re.compile(r'^(\\s+)rev:(\\s*)([\\'\"]?)([^\\s#]+)(.*)(\\r?\\n)$')\n\n\ndef _original_lines(\n        path: str,\n        rev_infos: List[Optional[RevInfo]],\n        retry: bool = False,\n) -> Tuple[List[str], List[int]]:\n    \"\"\"detect `rev:` lines or reformat the file\"\"\"\n    with open(path, newline='') as f:\n        original = f.read()\n\n    lines = original.splitlines(True)\n    idxs = [i for i, line in enumerate(lines) if REV_LINE_RE.match(line)]\n    if len(idxs) == len(rev_infos):\n        return lines, idxs\n    elif retry:\n        raise AssertionError('could not find rev lines')\n    else:\n        with open(path, 'w') as f:\n            f.write(yaml_dump(yaml_load(original)))\n        return _original_lines(path, rev_infos, retry=True)\n\n\ndef _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:\n    lines, idxs = _original_lines(path, rev_infos)\n\n    for idx, rev_info in zip(idxs, rev_infos):\n        if rev_info is None:\n            continue\n        match = REV_LINE_RE.match(lines[idx])\n        assert match is not None\n        new_rev_s = yaml_dump({'rev': rev_info.rev}, default_style=match[3])\n        new_rev = new_rev_s.split(':', 1)[1].strip()\n        if rev_info.frozen is not None:\n            comment = f'  # frozen: {rev_info.frozen}'\n        elif match[5].strip().startswith('# frozen:'):\n            comment = ''\n        else:\n            comment = match[5]\n        lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[6]}'\n\n    with open(path, 'w', newline='') as f:\n        f.write(''.join(lines))\n\n\ndef autoupdate(\n        config_file: str,\n        store: Store,\n        tags_only: bool,\n        freeze: bool,\n        repos: Sequence[str] = (),\n) -> int:\n    \"\"\"Auto-update the pre-commit config to the latest versions of repos.\"\"\"\n    migrate_config(config_file, quiet=True)\n    retv = 0\n    rev_infos: List[Optional[RevInfo]] = []\n    changed = False\n\n    config = load_config(config_file)\n    for repo_config in config['repos']:\n        if repo_config['repo'] in {LOCAL, META}:\n            continue\n\n        info = RevInfo.from_config(repo_config)\n        if repos and info.repo not in repos:\n            rev_infos.append(None)\n            continue\n\n        output.write(f'Updating {info.repo} ... ')\n        new_info = info.update(tags_only=tags_only, freeze=freeze)\n        try:\n            _check_hooks_still_exist_at_rev(repo_config, new_info, store)\n        except RepositoryCannotBeUpdatedError as error:\n            output.write_line(error.args[0])\n            rev_infos.append(None)\n            retv = 1\n            continue\n\n        if new_info.rev != info.rev:\n            changed = True\n            if new_info.frozen:\n                updated_to = f'{new_info.frozen} (frozen)'\n            else:\n                updated_to = new_info.rev\n            msg = f'updating {info.rev} -> {updated_to}.'\n            output.write_line(msg)\n            rev_infos.append(new_info)\n        else:\n            output.write_line('already up to date.')\n            rev_infos.append(None)\n\n    if changed:\n        _write_new_config(config_file, rev_infos)\n\n    return retv\n", "path": "pre_commit/commands/autoupdate.py"}]}