Skip to content

Commit 98d8a3d

Browse files
mjay-taskizeasottile
authored andcommitted
Maintain scalar quoting style when autoupdate re-writes rev
If rev is wrapped in single or double quotes (e.g. due to a yamllint quoted-strings rule), when re-writing the rev to update it, honour the existing quotation style
1 parent f455312 commit 98d8a3d

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

pre_commit/commands/autoupdate.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ def _check_hooks_still_exist_at_rev(
8484
)
8585

8686

87-
REV_LINE_RE = re.compile(r'^(\s+)rev:(\s*)([^\s#]+)(.*)(\r?\n)$', re.DOTALL)
87+
REV_LINE_RE = re.compile(
88+
r'^(\s+)rev:(\s*)([\'"]?)([^\s#]+)(.*)(\r?\n)$', re.DOTALL,
89+
)
8890

8991

9092
def _original_lines(
@@ -116,15 +118,15 @@ def _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:
116118
continue
117119
match = REV_LINE_RE.match(lines[idx])
118120
assert match is not None
119-
new_rev_s = yaml_dump({'rev': rev_info.rev})
121+
new_rev_s = yaml_dump({'rev': rev_info.rev}, default_style=match[3])
120122
new_rev = new_rev_s.split(':', 1)[1].strip()
121123
if rev_info.frozen is not None:
122124
comment = f' # frozen: {rev_info.frozen}'
123-
elif match[4].strip().startswith('# frozen:'):
125+
elif match[5].strip().startswith('# frozen:'):
124126
comment = ''
125127
else:
126-
comment = match[4]
127-
lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[5]}'
128+
comment = match[5]
129+
lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[6]}'
128130

129131
with open(path, 'w', newline='') as f:
130132
f.write(''.join(lines))

pre_commit/util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@
3636
Dumper = getattr(yaml, 'CSafeDumper', yaml.SafeDumper)
3737

3838

39-
def yaml_dump(o: Any) -> str:
39+
def yaml_dump(o: Any, **kwargs: Any) -> str:
4040
# when python/mypy#1484 is solved, this can be `functools.partial`
4141
return yaml.dump(
4242
o, Dumper=Dumper, default_flow_style=False, indent=4, sort_keys=False,
43+
**kwargs,
4344
)
4445

4546

tests/commands/autoupdate_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,23 @@ def test_updates_old_format_to_new_format(tmpdir, capsys, store):
474474
)
475475
out, _ = capsys.readouterr()
476476
assert out == 'Configuration has been migrated.\n'
477+
478+
479+
def test_maintains_rev_quoting_style(tmpdir, out_of_date, store):
480+
fmt = (
481+
'repos:\n'
482+
'- repo: {path}\n'
483+
' rev: "{rev}"\n'
484+
' hooks:\n'
485+
' - id: foo\n'
486+
'- repo: {path}\n'
487+
" rev: '{rev}'\n"
488+
' hooks:\n'
489+
' - id: foo\n'
490+
)
491+
cfg = tmpdir.join(C.CONFIG_FILE)
492+
cfg.write(fmt.format(path=out_of_date.path, rev=out_of_date.original_rev))
493+
494+
assert autoupdate(str(cfg), store, freeze=False, tags_only=False) == 0
495+
expected = fmt.format(path=out_of_date.path, rev=out_of_date.head_rev)
496+
assert cfg.read() == expected

0 commit comments

Comments
 (0)