Revision 5d3c30df

b/Makefile.am
21 21
BUILD_BASH_COMPLETION = $(top_srcdir)/autotools/build-bash-completion
22 22
RUN_IN_TEMPDIR = $(top_srcdir)/autotools/run-in-tempdir
23 23
CHECK_PYTHON_CODE = $(top_srcdir)/autotools/check-python-code
24
CHECK_HEADER = $(top_srcdir)/autotools/check-header
24 25
CHECK_MAN = $(top_srcdir)/autotools/check-man
25 26
CHECK_VERSION = $(top_srcdir)/autotools/check-version
26 27
CHECK_NEWS = $(top_srcdir)/autotools/check-news
......
560 561
	pylintrc \
561 562
	autotools/build-bash-completion \
562 563
	autotools/build-rpc \
564
	autotools/check-header \
563 565
	autotools/check-python-code \
564 566
	autotools/check-imports \
565 567
	autotools/check-man \
......
804 806
check_python_code = \
805 807
	$(BUILD_BASH_COMPLETION) \
806 808
	$(CHECK_IMPORTS) \
809
	$(CHECK_HEADER) \
807 810
	$(DOCPP) \
808 811
	$(all_python_code)
809 812

  
......
815 818
	$(pkglib_python_scripts) \
816 819
	$(BUILD_BASH_COMPLETION) \
817 820
	$(CHECK_IMPORTS) \
821
	$(CHECK_HEADER) \
818 822
	$(DOCPP) \
819 823
	$(PYTHON_BOOTSTRAP)
820 824

  
......
829 833
	$(dist_tools_PYTHON) \
830 834
	$(pkglib_python_scripts) \
831 835
	$(BUILD_BASH_COMPLETION) \
836
	$(CHECK_HEADER) \
832 837
	$(DOCPP) \
833 838
	$(PYTHON_BOOTSTRAP) \
834 839
	qa
......
1124 1129
.PHONY: check-local
1125 1130
check-local: check-dirs $(BUILT_SOURCES)
1126 1131
	$(CHECK_PYTHON_CODE) $(check_python_code)
1132
	PYTHONPATH=. $(CHECK_HEADER) $(check_python_code)
1127 1133
	$(CHECK_VERSION) $(VERSION) $(top_srcdir)/NEWS
1128 1134
	$(CHECK_NEWS) < $(top_srcdir)/NEWS
1129 1135
	PYTHONPATH=. $(RUN_IN_TEMPDIR) $(CURDIR)/$(CHECK_IMPORTS) . $(standalone_python_modules)
b/autotools/check-header
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""Script to verify file header.
23

  
24
"""
25

  
26
# pylint: disable-msg=C0103
27
# [C0103] Invalid name
28

  
29
import sys
30
import re
31
import itertools
32

  
33
from ganeti import constants
34
from ganeti import utils
35
from ganeti import compat
36

  
37

  
38
#: Assume header is always in the first 8kB of a file
39
_READ_SIZE = 8 * 1024
40

  
41
_GPLv2 = [
42
  "This program is free software; you can redistribute it and/or modify",
43
  "it under the terms of the GNU General Public License as published by",
44
  "the Free Software Foundation; either version 2 of the License, or",
45
  "(at your option) any later version.",
46
  "",
47
  "This program is distributed in the hope that it will be useful, but",
48
  "WITHOUT ANY WARRANTY; without even the implied warranty of",
49
  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU",
50
  "General Public License for more details.",
51
  "",
52
  "You should have received a copy of the GNU General Public License",
53
  "along with this program; if not, write to the Free Software",
54
  "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA",
55
  "02110-1301, USA.",
56
  ]
57

  
58

  
59
_SHEBANG = re.compile(r"^#(?:|!(?:/usr/bin/python(?:| -u)|/bin/(?:|ba)sh))$")
60
_COPYRIGHT_YEAR = r"20[01][0-9]"
61
_COPYRIGHT = re.compile(r"# Copyright \(C\) (%s(?:, %s)*) Google Inc\.$" %
62
                        (_COPYRIGHT_YEAR, _COPYRIGHT_YEAR))
63
_COPYRIGHT_DESC = "Copyright (C) <year>[, <year> ...] Google Inc."
64
_AUTOGEN = "# This file is automatically generated, do not edit!"
65

  
66

  
67
class HeaderError(Exception):
68
  pass
69

  
70

  
71
def _Fail(lineno, msg):
72
  raise HeaderError("Line %s: %s" % (lineno, msg))
73

  
74

  
75
def _CheckHeader(getline_fn):
76
  (lineno, line) = getline_fn()
77

  
78
  if line == _AUTOGEN:
79
    return
80

  
81
  if not _SHEBANG.match(line):
82
    _Fail(lineno, ("Must contain nothing but a hash character (#) or a"
83
                   " shebang line (e.g. #!/bin/bash)"))
84

  
85
  (lineno, line) = getline_fn()
86

  
87
  if line == _AUTOGEN:
88
    return
89

  
90
  if line != "#":
91
    _Fail(lineno, "Must contain nothing but hash character (#)")
92

  
93
  (lineno, line) = getline_fn()
94
  if line:
95
    _Fail(lineno, "Must be empty")
96

  
97
  (lineno, line) = getline_fn()
98
  if not _COPYRIGHT.match(line):
99
    _Fail(lineno, "Must contain copyright information (%s)" % _COPYRIGHT_DESC)
100

  
101
  (lineno, line) = getline_fn()
102
  if line != "#":
103
    _Fail(lineno, "Must contain nothing but hash character (#)")
104

  
105
  for licence_line in _GPLv2:
106
    (lineno, line) = getline_fn()
107
    if line != ("# %s" % licence_line).rstrip():
108
      _Fail(lineno, "Does not match expected licence line (%s)" % licence_line)
109

  
110
  (lineno, line) = getline_fn()
111
  if line:
112
    _Fail(lineno, "Must be empty")
113

  
114

  
115
def Main():
116
  """Main program.
117

  
118
  """
119
  fail = False
120

  
121
  for filename in sys.argv[1:]:
122
    content = utils.ReadFile(filename, size=_READ_SIZE)
123
    lines = zip(itertools.count(1), content.splitlines())
124

  
125
    try:
126
      _CheckHeader(compat.partial(lines.pop, 0))
127
    except HeaderError, err:
128
      report = str(err)
129
      print "%s: %s" % (filename, report)
130
      fail = True
131

  
132
  if fail:
133
    sys.exit(constants.EXIT_FAILURE)
134
  else:
135
    sys.exit(constants.EXIT_SUCCESS)
136

  
137

  
138
if __name__ == "__main__":
139
  Main()

Also available in: Unified diff