88import requests
99
1010
11- DSA = namedtuple ('DSA' , ('number' , 'package' , 'link' , 'description' , 'date' ))
11+ DSA = namedtuple ('DSA' , ('number' , 'revision' , ' package' , 'link' , 'description' , 'date' ))
1212last_seen = None
13+ last_seen_rev = None
1314
1415
1516def dsa_list ():
@@ -18,16 +19,17 @@ def dsa_list():
1819
1920 root = ElementTree .fromstring (req .content )
2021 for item in root .iter ('{http://purl.org/rss/1.0/}item' ):
21- # title is of the form "DSA-3804 linux - security update"
22+ # title is of the form "DSA-5535-1 firefox-esr - security update"
2223 title = item .find ('{http://purl.org/rss/1.0/}title' )
2324 assert title is not None
2425 assert title .text is not None
25- # group 1: dsa number, group 2: optional package name
26+ # group 1: dsa number, group 2: revision, group 3: optional package name
2627 # line ends with the type of notice, see DSA-4204, DSA-4205 for examples
27- m = re .match (r'DSA-(\d+) ?(.+)? - ' , title .text )
28+ m = re .match (r'DSA-(\d+)-(\d+) ?(.+)? - ' , title .text )
2829 assert m , title .text
2930 dsa_num = int (m .group (1 ))
30- package = m .group (2 )
31+ dsa_rev = int (m .group (2 ))
32+ package = m .group (3 )
3133 link_elt = item .find ('{http://purl.org/rss/1.0/}link' )
3234 assert link_elt is not None
3335 link = link_elt .text
@@ -46,6 +48,7 @@ def dsa_list():
4648
4749 yield DSA (
4850 number = dsa_num ,
51+ revision = dsa_rev ,
4952 package = package ,
5053 link = link ,
5154 description = description ,
@@ -68,15 +71,32 @@ def summarize(description, limit=256):
6871def get_new_dsas ():
6972 """Return new DSA summary lines."""
7073 global last_seen
74+ global last_seen_rev
7175 lines : List [str ] = []
7276 # exceptions (including HTTP error codes) are handled in timer.py
7377 dsas = list (dsa_list ())
78+ # DSA RSS feed is newest first, reverse to make sure the first
79+ # revision doesn't get skipped if there's a second revision
80+ dsas .reverse ()
7481
75- if last_seen is not None :
76- for dsa in sorted (dsas , key = operator .attrgetter ('number' )):
77- if last_seen < dsa .number :
78- lines .append ('\x02 \x03 04[DSA {dsa.number}] {dsa.package} - {dsa.link}' .format (dsa = dsa ))
79- lines .append ('\x03 04' + summarize (dsa .description ))
82+ if last_seen_rev is not None :
83+ if last_seen is not None :
84+ for dsa in sorted (dsas , key = operator .attrgetter ('number' )):
85+ if last_seen < dsa .number or (
86+ last_seen == dsa .number
87+ and last_seen_rev < dsa .revision
88+ ):
89+ lines .append (
90+ (
91+ '\x02 \x03 04[DSA-{dsa.number}-{dsa.revision}] '
92+ '{dsa.package} - {dsa.link}'
93+ ).format (dsa = dsa ),
94+ )
95+ lines .append ('\x03 04' + summarize (dsa .description ))
96+ last_seen = dsa .number
97+ last_seen_rev = dsa .revision
98+ else :
99+ last_seen_rev = 1
80100
81101 last_seen = max (dsa .number for dsa in dsas )
82102 return lines
0 commit comments