Skip to content

Commit 4f045cb

Browse files
committed
perform autoupdate without Store contention
1 parent 27d77fc commit 4f045cb

File tree

4 files changed

+71
-66
lines changed

4 files changed

+71
-66
lines changed

pre_commit/commands/autoupdate.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from pre_commit.clientlib import LOCAL
1717
from pre_commit.clientlib import META
1818
from pre_commit.commands.migrate_config import migrate_config
19-
from pre_commit.store import Store
2019
from pre_commit.util import CalledProcessError
2120
from pre_commit.util import cmd_output
2221
from pre_commit.util import cmd_output_b
@@ -27,11 +26,12 @@
2726
class RevInfo(NamedTuple):
2827
repo: str
2928
rev: str
30-
frozen: str | None
29+
frozen: str | None = None
30+
hook_ids: frozenset[str] = frozenset()
3131

3232
@classmethod
3333
def from_config(cls, config: dict[str, Any]) -> RevInfo:
34-
return cls(config['repo'], config['rev'], None)
34+
return cls(config['repo'], config['rev'])
3535

3636
def update(self, tags_only: bool, freeze: bool) -> RevInfo:
3737
with tempfile.TemporaryDirectory() as tmp:
@@ -63,7 +63,19 @@ def update(self, tags_only: bool, freeze: bool) -> RevInfo:
6363
exact = cmd_output(*_git, 'rev-parse', rev)[1].strip()
6464
if exact != rev:
6565
rev, frozen = exact, rev
66-
return self._replace(rev=rev, frozen=frozen)
66+
67+
try:
68+
cmd_output(*_git, 'checkout', rev, '--', C.MANIFEST_FILE)
69+
except CalledProcessError:
70+
pass # this will be caught by manifest validating code
71+
try:
72+
manifest = load_manifest(os.path.join(tmp, C.MANIFEST_FILE))
73+
except InvalidManifestError as e:
74+
raise RepositoryCannotBeUpdatedError(str(e))
75+
else:
76+
hook_ids = frozenset(hook['id'] for hook in manifest)
77+
78+
return self._replace(rev=rev, frozen=frozen, hook_ids=hook_ids)
6779

6880

6981
class RepositoryCannotBeUpdatedError(RuntimeError):
@@ -73,17 +85,10 @@ class RepositoryCannotBeUpdatedError(RuntimeError):
7385
def _check_hooks_still_exist_at_rev(
7486
repo_config: dict[str, Any],
7587
info: RevInfo,
76-
store: Store,
7788
) -> None:
78-
try:
79-
path = store.clone(repo_config['repo'], info.rev)
80-
manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
81-
except InvalidManifestError as e:
82-
raise RepositoryCannotBeUpdatedError(str(e))
83-
8489
# See if any of our hooks were deleted with the new commits
8590
hooks = {hook['id'] for hook in repo_config['hooks']}
86-
hooks_missing = hooks - {hook['id'] for hook in manifest}
91+
hooks_missing = hooks - info.hook_ids
8792
if hooks_missing:
8893
raise RepositoryCannotBeUpdatedError(
8994
f'Cannot update because the update target is missing these '
@@ -139,7 +144,6 @@ def _write_new_config(path: str, rev_infos: list[RevInfo | None]) -> None:
139144

140145
def autoupdate(
141146
config_file: str,
142-
store: Store,
143147
tags_only: bool,
144148
freeze: bool,
145149
repos: Sequence[str] = (),
@@ -161,9 +165,9 @@ def autoupdate(
161165
continue
162166

163167
output.write(f'Updating {info.repo} ... ')
164-
new_info = info.update(tags_only=tags_only, freeze=freeze)
165168
try:
166-
_check_hooks_still_exist_at_rev(repo_config, new_info, store)
169+
new_info = info.update(tags_only=tags_only, freeze=freeze)
170+
_check_hooks_still_exist_at_rev(repo_config, new_info)
167171
except RepositoryCannotBeUpdatedError as error:
168172
output.write_line(error.args[0])
169173
rev_infos.append(None)

pre_commit/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ def _add_cmd(name: str, *, help: str) -> argparse.ArgumentParser:
368368

369369
if args.command == 'autoupdate':
370370
return autoupdate(
371-
args.config, store,
371+
args.config,
372372
tags_only=not args.bleeding_edge,
373373
freeze=args.freeze,
374374
repos=args.repos,

0 commit comments

Comments
 (0)