diff --git a/dzonegit.py b/dzonegit.py index bbca859..9e6b371 100644 --- a/dzonegit.py +++ b/dzonegit.py @@ -14,6 +14,9 @@ from pathlib import Path from string import Template +SERIAL_SMUDGE_TAG = "DZONEGIT_DO_NOT_CHANGE_OLD_SERIAL_" + + class HookException(ValueError): """Exception raised when there is an error in input data. @@ -493,3 +496,32 @@ def post_receive(stdin=sys.stdin): cmd.append(z) print("Calling {}…".format(" ".join(cmd))) subprocess.run(cmd) + + +def clean_serial(stdin=sys.stdin): + """ Git filter command to replace smudged serial with an increased one. """ + for line in stdin: + m = re.search( + r"(\s){}([0-9]+)(\s)".format(SERIAL_SMUDGE_TAG), + line, + ) + if m: + oldserial = m.group(2) + newserial = get_increased_serial(oldserial) + line = line.replace(SERIAL_SMUDGE_TAG + oldserial, newserial) + print(line, end="") + + +def smudge_serial(stdin=sys.stdin): + """ Git filter command to smudge SOA serial number. """ + sys.stderr.write("Smudging {}…\n".format(sys.argv)) + zonedata = stdin.read() + if SERIAL_SMUDGE_TAG not in zonedata: + zonedata = re.sub( + r'(^.*\sSOA\s.+?\s)([0-9]+[^0-9])', + r'\g<1>{}\g<2>'.format(SERIAL_SMUDGE_TAG), + zonedata, + count=1, + flags=re.DOTALL | re.IGNORECASE | re.MULTILINE, + ) + print(zonedata, end="") diff --git a/setup.py b/setup.py index 30802cf..1af417e 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,8 @@ setup( "dzonegit-pre-receive = dzonegit:pre_receive", "dzonegit-post-receive = dzonegit:post_receive", "dzonegit-update = dzonegit:update", + "dzonegit-smudge-serial = dzonegit:smudge_serial", + "dzonegit-clean-serial = dzonegit:clean_serial", ], }, classifiers=[ diff --git a/test_dzonegit.py b/test_dzonegit.py index ffb7d17..156aace 100644 --- a/test_dzonegit.py +++ b/test_dzonegit.py @@ -332,3 +332,42 @@ def test_get_zone_wildcards(): "a.long.zone.name", "*.long.zone.name", "*.zone.name", "*.name", "*", ] + + +def test_smudge_serial(capsys): + stdin = StringIO(""" +@ 60 IN SOA ns hm ( + 60 ; serial + 60 ; refresh + 60 ; retry + 60 ; expire + 60 ; minimum + ) + 60 NS ns.example.org. +""") + dzonegit.smudge_serial(stdin) + stdout = capsys.readouterr().out + + assert "{}60 ; serial".format(dzonegit.SERIAL_SMUDGE_TAG) in stdout + stdin = StringIO(stdout) + dzonegit.smudge_serial(stdin) + assert stdout == capsys.readouterr().out + + +def test_clean_serial(capsys): + stdin = StringIO(""" +@ 60 IN SOA ns hm ( + {}60 ; serial + 60 ; refresh + 60 ; retry + 60 ; expire + 60 ; minimum + ) + 60 NS ns.example.org. +""".format(dzonegit.SERIAL_SMUDGE_TAG)) + dzonegit.clean_serial(stdin) + stdout = capsys.readouterr().out + assert " 61 ; serial" in stdout + stdin = StringIO(stdout) + dzonegit.clean_serial(stdin) + assert stdout == capsys.readouterr().out