Statistics
| Branch: | Tag: | Revision:

root / autotools / check-news @ d466fd8b

History | View | Annotate | Download (4.7 kB)

1 7385c51d Michael Hanselmann
#!/usr/bin/python
2 7385c51d Michael Hanselmann
#
3 7385c51d Michael Hanselmann
4 1657353c Michael Hanselmann
# Copyright (C) 2011, 2012, 2013 Google Inc.
5 7385c51d Michael Hanselmann
#
6 7385c51d Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 7385c51d Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 7385c51d Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 7385c51d Michael Hanselmann
# (at your option) any later version.
10 7385c51d Michael Hanselmann
#
11 7385c51d Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 7385c51d Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 7385c51d Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 7385c51d Michael Hanselmann
# General Public License for more details.
15 7385c51d Michael Hanselmann
#
16 7385c51d Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 7385c51d Michael Hanselmann
# along with this program; if not, write to the Free Software
18 7385c51d Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 7385c51d Michael Hanselmann
# 02110-1301, USA.
20 7385c51d Michael Hanselmann
21 7385c51d Michael Hanselmann
22 7385c51d Michael Hanselmann
"""Script to check NEWS file.
23 7385c51d Michael Hanselmann
24 7385c51d Michael Hanselmann
"""
25 7385c51d Michael Hanselmann
26 f0fa05ac Iustin Pop
# pylint: disable=C0103
27 f0fa05ac Iustin Pop
# [C0103] Invalid name
28 f0fa05ac Iustin Pop
29 7385c51d Michael Hanselmann
import sys
30 7385c51d Michael Hanselmann
import time
31 7385c51d Michael Hanselmann
import datetime
32 7385c51d Michael Hanselmann
import locale
33 7385c51d Michael Hanselmann
import fileinput
34 7385c51d Michael Hanselmann
import re
35 d466fd8b Guido Trotter
import os
36 7385c51d Michael Hanselmann
37 7385c51d Michael Hanselmann
38 7385c51d Michael Hanselmann
DASHES_RE = re.compile(r"^\s*-+\s*$")
39 7385c51d Michael Hanselmann
RELEASED_RE = re.compile(r"^\*\(Released (?P<day>[A-Z][a-z]{2}),"
40 7385c51d Michael Hanselmann
                         r" (?P<date>.+)\)\*$")
41 7385c51d Michael Hanselmann
UNRELEASED_RE = re.compile(r"^\*\(unreleased\)\*$")
42 d466fd8b Guido Trotter
VERSION_RE = re.compile(r"^Version (\d+(\.\d+)+( (beta|rc)\d+)?)$")
43 7385c51d Michael Hanselmann
44 1657353c Michael Hanselmann
#: How many days release timestamps may be in the future
45 1657353c Michael Hanselmann
TIMESTAMP_FUTURE_DAYS_MAX = 3
46 1657353c Michael Hanselmann
47 f0fa05ac Iustin Pop
errors = []
48 f0fa05ac Iustin Pop
49 f0fa05ac Iustin Pop
50 f0fa05ac Iustin Pop
def Error(msg):
51 f0fa05ac Iustin Pop
  """Log an error for later display.
52 f0fa05ac Iustin Pop
53 f0fa05ac Iustin Pop
  """
54 f0fa05ac Iustin Pop
  errors.append(msg)
55 f0fa05ac Iustin Pop
56 f0fa05ac Iustin Pop
57 f0fa05ac Iustin Pop
def ReqNLines(req, count_empty, lineno, line):
58 f0fa05ac Iustin Pop
  """Check if we have N empty lines.
59 f0fa05ac Iustin Pop
60 f0fa05ac Iustin Pop
  """
61 f0fa05ac Iustin Pop
  if count_empty < req:
62 f0fa05ac Iustin Pop
    Error("Line %s: Missing empty line(s) before %s,"
63 f0fa05ac Iustin Pop
          " %d needed but got only %d" %
64 f0fa05ac Iustin Pop
          (lineno, line, req, count_empty))
65 f0fa05ac Iustin Pop
  if count_empty > req:
66 f0fa05ac Iustin Pop
    Error("Line %s: Too many empty lines before %s,"
67 f0fa05ac Iustin Pop
          " %d needed but got %d" %
68 f0fa05ac Iustin Pop
          (lineno, line, req, count_empty))
69 f0fa05ac Iustin Pop
70 7385c51d Michael Hanselmann
71 7385c51d Michael Hanselmann
def main():
72 7385c51d Michael Hanselmann
  # Ensure "C" locale is used
73 7385c51d Michael Hanselmann
  curlocale = locale.getlocale()
74 7385c51d Michael Hanselmann
  if curlocale != (None, None):
75 f0fa05ac Iustin Pop
    Error("Invalid locale %s" % curlocale)
76 7385c51d Michael Hanselmann
77 d466fd8b Guido Trotter
  # Get the release version, but replace "~" with " " as the version
78 d466fd8b Guido Trotter
  # in the NEWS file uses spaces for beta and rc releases.
79 d466fd8b Guido Trotter
  release = os.environ.get('RELEASE', "").replace("~", " ")
80 d466fd8b Guido Trotter
81 7385c51d Michael Hanselmann
  prevline = None
82 7385c51d Michael Hanselmann
  expect_date = False
83 51ef5fe0 Guido Trotter
  count_empty = 0
84 d466fd8b Guido Trotter
  allow_unreleased = True
85 d466fd8b Guido Trotter
  found_versions = set()
86 7385c51d Michael Hanselmann
87 7385c51d Michael Hanselmann
  for line in fileinput.input():
88 7385c51d Michael Hanselmann
    line = line.rstrip("\n")
89 7385c51d Michael Hanselmann
90 d466fd8b Guido Trotter
    version_match = VERSION_RE.match(line)
91 d466fd8b Guido Trotter
    if version_match:
92 f0fa05ac Iustin Pop
      ReqNLines(2, count_empty, fileinput.filelineno(), line)
93 d466fd8b Guido Trotter
      version = version_match.group(1)
94 d466fd8b Guido Trotter
      if version in found_versions:
95 d466fd8b Guido Trotter
        Error("Line %s: Duplicate release %s found" %
96 d466fd8b Guido Trotter
              (fileinput.filelineno(), version))
97 d466fd8b Guido Trotter
      found_versions.add(version)
98 d466fd8b Guido Trotter
      if version == release:
99 d466fd8b Guido Trotter
        allow_unreleased = False
100 d466fd8b Guido Trotter
101 d466fd8b Guido Trotter
    unreleased_match = UNRELEASED_RE.match(line)
102 d466fd8b Guido Trotter
    if unreleased_match and not allow_unreleased:
103 d466fd8b Guido Trotter
      Error("Line %s: Unreleased version after current release %s" %
104 d466fd8b Guido Trotter
            (fileinput.filelineno(), release))
105 d466fd8b Guido Trotter
106 d466fd8b Guido Trotter
    if unreleased_match or RELEASED_RE.match(line):
107 f0fa05ac Iustin Pop
      ReqNLines(1, count_empty, fileinput.filelineno(), line)
108 51ef5fe0 Guido Trotter
109 51ef5fe0 Guido Trotter
    if line:
110 51ef5fe0 Guido Trotter
      count_empty = 0
111 51ef5fe0 Guido Trotter
    else:
112 51ef5fe0 Guido Trotter
      count_empty += 1
113 51ef5fe0 Guido Trotter
114 7385c51d Michael Hanselmann
    if DASHES_RE.match(line):
115 51ef5fe0 Guido Trotter
      if not VERSION_RE.match(prevline):
116 f0fa05ac Iustin Pop
        Error("Line %s: Invalid title" %
117 f0fa05ac Iustin Pop
              (fileinput.filelineno() - 1))
118 51ef5fe0 Guido Trotter
      if len(line) != len(prevline):
119 f0fa05ac Iustin Pop
        Error("Line %s: Invalid dashes length" %
120 f0fa05ac Iustin Pop
              (fileinput.filelineno()))
121 7385c51d Michael Hanselmann
      expect_date = True
122 7385c51d Michael Hanselmann
123 7385c51d Michael Hanselmann
    elif expect_date:
124 7385c51d Michael Hanselmann
      if not line:
125 7385c51d Michael Hanselmann
        # Ignore empty lines
126 7385c51d Michael Hanselmann
        continue
127 7385c51d Michael Hanselmann
128 7385c51d Michael Hanselmann
      if UNRELEASED_RE.match(line):
129 7385c51d Michael Hanselmann
        # Ignore unreleased versions
130 7385c51d Michael Hanselmann
        expect_date = False
131 7385c51d Michael Hanselmann
        continue
132 7385c51d Michael Hanselmann
133 7385c51d Michael Hanselmann
      m = RELEASED_RE.match(line)
134 7385c51d Michael Hanselmann
      if not m:
135 f0fa05ac Iustin Pop
        Error("Line %s: Invalid release line" % fileinput.filelineno())
136 9495d2f2 Guido Trotter
        expect_date = False
137 9495d2f2 Guido Trotter
        continue
138 7385c51d Michael Hanselmann
139 7385c51d Michael Hanselmann
      # Including the weekday in the date string does not work as time.strptime
140 7385c51d Michael Hanselmann
      # would return an inconsistent result if the weekday is incorrect.
141 7385c51d Michael Hanselmann
      parsed_ts = time.mktime(time.strptime(m.group("date"), "%d %b %Y"))
142 7385c51d Michael Hanselmann
      parsed = datetime.date.fromtimestamp(parsed_ts)
143 1657353c Michael Hanselmann
      today = datetime.date.today()
144 1657353c Michael Hanselmann
145 1657353c Michael Hanselmann
      if (parsed - datetime.timedelta(TIMESTAMP_FUTURE_DAYS_MAX)) > today:
146 1657353c Michael Hanselmann
        Error("Line %s: %s is more than %s days in the future (today is %s)" %
147 1657353c Michael Hanselmann
              (fileinput.filelineno(), parsed, TIMESTAMP_FUTURE_DAYS_MAX,
148 1657353c Michael Hanselmann
               today))
149 1657353c Michael Hanselmann
150 7385c51d Michael Hanselmann
      weekday = parsed.strftime("%a")
151 7385c51d Michael Hanselmann
152 7385c51d Michael Hanselmann
      # Check weekday
153 7385c51d Michael Hanselmann
      if m.group("day") != weekday:
154 f0fa05ac Iustin Pop
        Error("Line %s: %s was/is a %s, not %s" %
155 f0fa05ac Iustin Pop
              (fileinput.filelineno(), parsed, weekday,
156 f0fa05ac Iustin Pop
               m.group("day")))
157 7385c51d Michael Hanselmann
158 7385c51d Michael Hanselmann
      expect_date = False
159 7385c51d Michael Hanselmann
160 7385c51d Michael Hanselmann
    prevline = line
161 7385c51d Michael Hanselmann
162 f0fa05ac Iustin Pop
  if errors:
163 f0fa05ac Iustin Pop
    for msg in errors:
164 f0fa05ac Iustin Pop
      print >> sys.stderr, msg
165 f0fa05ac Iustin Pop
    sys.exit(1)
166 f0fa05ac Iustin Pop
  else:
167 f0fa05ac Iustin Pop
    sys.exit(0)
168 7385c51d Michael Hanselmann
169 7385c51d Michael Hanselmann
170 7385c51d Michael Hanselmann
if __name__ == "__main__":
171 7385c51d Michael Hanselmann
  main()