diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py index 8c9fdd7d..87f6d53d 100644 --- a/pre_commit/commands/autoupdate.py +++ b/pre_commit/commands/autoupdate.py @@ -84,7 +84,9 @@ def _check_hooks_still_exist_at_rev( ) -REV_LINE_RE = re.compile(r'^(\s+)rev:(\s*)([^\s#]+)(.*)(\r?\n)$', re.DOTALL) +REV_LINE_RE = re.compile( + r'^(\s+)rev:(\s*)([\'"]?)([^\s#]+)(.*)(\r?\n)$', re.DOTALL, +) def _original_lines( @@ -116,15 +118,15 @@ def _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None: continue match = REV_LINE_RE.match(lines[idx]) assert match is not None - new_rev_s = yaml_dump({'rev': rev_info.rev}) + new_rev_s = yaml_dump({'rev': rev_info.rev}, default_style=match[3]) new_rev = new_rev_s.split(':', 1)[1].strip() if rev_info.frozen is not None: comment = f' # frozen: {rev_info.frozen}' - elif match[4].strip().startswith('# frozen:'): + elif match[5].strip().startswith('# frozen:'): comment = '' else: - comment = match[4] - lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[5]}' + comment = match[5] + lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[6]}' with open(path, 'w', newline='') as f: f.write(''.join(lines)) diff --git a/pre_commit/util.py b/pre_commit/util.py index 2db579a5..0338b373 100644 --- a/pre_commit/util.py +++ b/pre_commit/util.py @@ -36,10 +36,11 @@ yaml_load = functools.partial(yaml.load, Loader=Loader) Dumper = getattr(yaml, 'CSafeDumper', yaml.SafeDumper) -def yaml_dump(o: Any) -> str: +def yaml_dump(o: Any, **kwargs: Any) -> str: # when python/mypy#1484 is solved, this can be `functools.partial` return yaml.dump( o, Dumper=Dumper, default_flow_style=False, indent=4, sort_keys=False, + **kwargs, ) diff --git a/tests/commands/autoupdate_test.py b/tests/commands/autoupdate_test.py index fbeee728..bd89c1db 100644 --- a/tests/commands/autoupdate_test.py +++ b/tests/commands/autoupdate_test.py @@ -474,3 +474,23 @@ def test_updates_old_format_to_new_format(tmpdir, capsys, store): ) out, _ = capsys.readouterr() assert out == 'Configuration has been migrated.\n' + + +def test_maintains_rev_quoting_style(tmpdir, out_of_date, store): + fmt = ( + 'repos:\n' + '- repo: {path}\n' + ' rev: "{rev}"\n' + ' hooks:\n' + ' - id: foo\n' + '- repo: {path}\n' + " rev: '{rev}'\n" + ' hooks:\n' + ' - id: foo\n' + ) + cfg = tmpdir.join(C.CONFIG_FILE) + cfg.write(fmt.format(path=out_of_date.path, rev=out_of_date.original_rev)) + + assert autoupdate(str(cfg), store, freeze=False, tags_only=False) == 0 + expected = fmt.format(path=out_of_date.path, rev=out_of_date.head_rev) + assert cfg.read() == expected