1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/env python3
"""
Update (or check) the contents of release_date.rs,
in preparation for a software release.
"""
import argparse
import calendar
import os
import sys
import re
import time
from pathlib import Path
def parse_date(s: str) -> time.struct_time:
return time.strptime(s, "%Y-%m-%d")
WARNING_TEXT = """\
// DO NOT EDIT MANUALLY.
// This file was automatically generated by maint/update-release-date.
"""
SEC_PER_DAY = 86400
DATE_RE = re.compile(r"const ARTI_CLIENT_RELEASE_DATE: &str = \"([-\d]*)\";")
def check_date(filename: Path, date: time.struct_time, tolerance: int):
contents = filename.open("r").read()
if not contents.startswith(WARNING_TEXT):
print(f"{filename} does not start with our usual warning. Not proceding.")
sys.exit(1)
m = DATE_RE.search(contents)
if m is None:
print(f"Didn't find a date string in {filename}")
sys.exit(1)
found_date_str = m.group(1)
found_date = time.strptime(found_date_str, "%Y-%m-%d")
released = calendar.timegm(found_date)
now = calendar.timegm(date)
if abs(now - released) > tolerance * SEC_PER_DAY:
print(f"Release date of {found_date_str} is too far in the past or future!")
print("Run maint/update-release-date to correct this.")
sys.exit(1)
else:
print(f"Release date of {found_date_str} is okay.")
def update_date(filename: Path, date: time.struct_time):
contents = filename.open("r").read()
if not contents.startswith(WARNING_TEXT):
print(f"{filename} does not start with our usual warning. Not proceding.")
sys.exit(1)
date_text = time.strftime("%Y-%m-%d", date)
with filename.open("w") as f:
f.write(f"""\
{WARNING_TEXT}
//! Release date for arti-client.
//!
//! This module is automatically generated; do not edit by hand.
/// The approximate release date for this version of arti-client.
///
/// We use this release date in [`protostatus`](crate::protostatus)
/// to decide whether a consensus is new enough
/// that we should obey its recommendations.
///
/// (We do not warn or shut down based on recommendations
/// from consensuses older than our software:
/// the fact that we released _this_ version
/// indicates that a newer consensus probably permits this version.)
pub(crate) const ARTI_CLIENT_RELEASE_DATE: &str = "{date_text}";
""")
def run():
parser = argparse.ArgumentParser()
parser.add_argument("--check", action="store_true")
parser.add_argument(
"--tolerance", default=2, help="Tolerance in days (used with --check)"
)
parser.add_argument(
"--date", help="The target release date, if not today. YYYY-MM-DD form"
)
parser.add_argument("--filename", help="The rust module to check or update.")
args = parser.parse_args()
filename = (args.filename,)
check_only = args.check
tolerance = int(args.tolerance)
if args.date is None:
date = time.gmtime()
else:
date = parse_date(args.date)
if args.filename is None:
filename = (
Path(os.path.dirname(sys.argv[0])).parent.parent
/ "crates/arti-client/src/release_date.rs"
)
else:
filename = Path(args.filename)
if not filename.is_file():
print(f"{filename} does not exist; not proceding")
sys.exit(1)
if check_only:
check_date(filename, date, tolerance)
else:
update_date(filename, date)
if __name__ == "__main__":
run()
|