[Checkins] SVN: zope.repositorypolicy/trunk/ Import tools that can be used to:
Christian Theune
ct at gocept.com
Fri Mar 5 10:08:07 EST 2010
Log message for revision 109677:
Import tools that can be used to:
- continuously monitor the repository compliance
- check for issues in a working directory
- some helpers for fixing copyright headers
Changed:
A zope.repositorypolicy/trunk/
A zope.repositorypolicy/trunk/RULES.txt
A zope.repositorypolicy/trunk/bootstrap.py
A zope.repositorypolicy/trunk/buildout.cfg
A zope.repositorypolicy/trunk/setup.py
A zope.repositorypolicy/trunk/src/
A zope.repositorypolicy/trunk/src/zope/
A zope.repositorypolicy/trunk/src/zope/__init__.py
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
A zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py
-=-
Added: zope.repositorypolicy/trunk/RULES.txt
===================================================================
--- zope.repositorypolicy/trunk/RULES.txt (rev 0)
+++ zope.repositorypolicy/trunk/RULES.txt 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,15 @@
+
+- the rules are enforced on all top level subversion modules on the branches
+ trunk, develop
+
+- the rules are *not* enforced in the modules
+ Sandbox, ...
+
+
+- all copyright headers (c-style, python style) must be zope foundation
+
+- every package must have a license.txt which is ZPL 2.1
+- every package must have a copyright.txt according to ZPL 2.1 which points to
+ the Zope Foundation
+
+- exceptions to the rules are codified in each package in a special file
Property changes on: zope.repositorypolicy/trunk/RULES.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/bootstrap.py
===================================================================
--- zope.repositorypolicy/trunk/bootstrap.py (rev 0)
+++ zope.repositorypolicy/trunk/bootstrap.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 90478 2008-08-27 22:44:46Z georgyberdyshev $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+try:
+ import pkg_resources
+except ImportError:
+ ez = {}
+ exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+ import pkg_resources
+
+if sys.platform == 'win32':
+ def quote(c):
+ if ' ' in c:
+ return '"%s"' % c # work around spawn lamosity on windows
+ else:
+ return c
+else:
+ def quote (c):
+ return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws = pkg_resources.working_set
+
+if is_jython:
+ import subprocess
+
+ assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+ quote(tmpeggs), 'zc.buildout'],
+ env=dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ).wait() == 0
+
+else:
+ assert os.spawnle(
+ os.P_WAIT, sys.executable, quote (sys.executable),
+ '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Property changes on: zope.repositorypolicy/trunk/bootstrap.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/buildout.cfg
===================================================================
--- zope.repositorypolicy/trunk/buildout.cfg (rev 0)
+++ zope.repositorypolicy/trunk/buildout.cfg 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,8 @@
+[buildout]
+develop = .
+parts = egg
+
+[egg]
+recipe = zc.recipe.egg
+eggs = zope.repositorypolicy
+interpreter = py
Added: zope.repositorypolicy/trunk/setup.py
===================================================================
--- zope.repositorypolicy/trunk/setup.py (rev 0)
+++ zope.repositorypolicy/trunk/setup.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,27 @@
+from setuptools import setup, find_packages
+
+setup(
+ name='zope.repositorypolicy',
+ version='0.1dev',
+ author='Zope Developers',
+ author_email='zope-dev at zope.org',
+ url='http://pypi.python.org/pypi/zope.repositorypolicy',
+ description="""\
+ Tools to verify and help sustain policy compliance for projects in
+ svn.zope.org
+ """,
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ include_package_data=True,
+ zip_safe=False,
+ license='ZPL 2.1',
+ namespace_packages=['zope'],
+ install_requires=[
+ 'setuptools',
+ 'subvertpy'],
+ entry_points="""
+ [console_scripts]
+ zope-org-check-repos = zope.repositorypolicy.repository:main
+ zope-org-check-project = zope.repositorypolicy.project:main
+ zope-org-fix-project = zope.repositorypolicy.copyright:main
+ """)
Property changes on: zope.repositorypolicy/trunk/setup.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/__init__.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/__init__.py (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/__init__.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zope.repositorypolicy/trunk/src/zope/__init__.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1 @@
+# Make this a Python package
Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,34 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import sys
+import zope.repositorypolicy.project
+import StringIO
+
+
+class FixCopyrightHeaders(object):
+ """A simple helper to fix source file copyright headers."""
+
+ def __init__(self, working_dir, owner):
+ self.working_dir = working_dir
+ self.owner = owner
+
+ def run(self):
+ zope.repositorypolicy.project.walk_project_dir(
+ self.working_dir, self._fix_file)
+
+ def _fix_file(self, path):
+ print path
+ output = StringIO.StringIO()
+ for line in open(path):
+ m = zope.repositorypolicy.project.COPYRIGHT_PATTERN.match(line)
+ if m is not None:
+ line = '%sCopyright (c) %s %s%s' % (
+ m.group('lead'), m.group('periods'), self.owner,
+ m.group('tail'))
+ output.write(line)
+ open(path, 'w').write(output.getvalue())
+
+
+def main():
+ FixCopyrightHeaders(sys.argv[1], sys.argv[2]).run()
Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,44 @@
+Zope Public License (ZPL) Version 2.1
+
+A copyright notice accompanies this license document that identifies the
+copyright holders.
+
+This license has been certified as open source. It has also been designated as
+GPL compatible by the Free Software Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions in source code must retain the accompanying copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to endorse or promote
+products derived from this software without prior written permission from the
+copyright holders.
+
+4. The right to distribute this software or to use it for any purpose does not
+give you the right to use Servicemarks (sm) or Trademarks (tm) of the
+copyright
+holders. Use of them is covered by separate agreement with the copyright
+holders.
+
+5. If any files are modified, you must cause the modified files to carry
+prominent notices stating that you changed the files and the date of any
+change.
+
+Disclaimer
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,122 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import sys
+import os
+import os.path
+import subprocess
+import re
+
+COPYRIGHT_PATTERN = re.compile(
+ '^(?P<lead>.*)Copyright \\(c\\) '
+ '(?P<periods>[0-9\-, ]+) (?P<owner>.*?)(?P<tail>\W*)$')
+
+
+def walk_project_dir(root, callback):
+ def visit(args, dirname, names):
+ for name in list(names):
+ if name.startswith('.'):
+ names.remove(name)
+ continue
+ if name.endswith('.egg-info'):
+ names.remove(name)
+ continue
+ if os.path.splitext(name)[1] in [
+ '.so', '.pyc', '.pyo']:
+ continue
+ if os.path.isfile(os.path.join(dirname, name)):
+ path = os.path.join(dirname, name)
+ callback(path)
+ os.path.walk(root, visit, ())
+
+
+class Checker(object):
+
+ data_dir = os.path.join(os.path.dirname(__file__), 'data')
+ license_name = 'ZPL 2.1'
+ copyright_holder = 'Zope Foundation and Contributors'
+
+ def __init__(self, working_dir):
+ self.working_dir = working_dir
+ self.log = []
+
+ def run(self):
+ self.check_license_file()
+ self.check_egg_metadata()
+ self.check_copyright()
+
+ def check_license_file(self):
+ """Verifies license expression:
+
+ - the file LICENSE.txt exists and has a valid copy of the ZPL 2.1
+ - the file setup.py (if it exists) and is marked as ZPL 2.1
+
+ """
+ license = os.path.join(self.working_dir, 'LICENSE.txt')
+ if not os.path.isfile(license):
+ self.log.append('LICENSE.txt: Missing license file')
+ else:
+ license_content = open(license).read()
+ license_expected = open(
+ os.path.join(self.data_dir, 'ZPL-2.1.txt')).read()
+ if license_content != license_expected:
+ self.log.append('LICENSE.txt: Not a valid copy of ZPL 2.1')
+
+ def check_egg_metadata(self):
+ setup = os.path.join(self.working_dir, 'setup.py')
+ if os.path.isfile(setup):
+ s = subprocess.Popen([sys.executable, setup,
+ '--license', '--author'],
+ stdout=subprocess.PIPE)
+ s.wait()
+ metadata = s.stdout.readlines()
+ license = metadata[0].strip()
+ if license != self.license_name:
+ self.log.append(
+ 'setup.py: license not declared as "%s" (found: "%s")' %
+ (self.license_name, license))
+ author = metadata[1].strip()
+ if author != self.copyright_holder:
+ self.log.append(
+ 'setup.py: author not declared as "%s" '
+ '(found: "%s")' %
+ (self.copyright_holder, author))
+
+ def check_copyright(self):
+ """Verifies the copyright assignment to the Zope Foundation
+
+ - the file COPYRIGHT.txt exists and has correct content
+ - all copyright statements that can be found refer to the Zope
+ foundation
+
+ """
+ copyright = os.path.join(self.working_dir, 'COPYRIGHT.txt')
+ if not os.path.isfile(copyright):
+ self.log.append('COPYRIGHT.txt: Missing copyright file')
+ else:
+ content = open(copyright).read().strip()
+ if content != self.copyright_holder:
+ self.log.append(
+ 'COPYRIGHT.txt: not assigned to Zope Foundation '
+ '(found: "%s")' % content)
+ walk_project_dir(self.working_dir, self._check_copyright_file)
+
+ def _check_copyright_file(self, filename):
+ for i, line in enumerate(open(filename)):
+ m = COPYRIGHT_PATTERN.match(line)
+ if m is None:
+ continue
+ if m.group('owner') != self.copyright_holder:
+ self.log.append('%s:%i: incorrect copyright holder: %s' % (
+ filename.replace(self.working_dir + '/', ''), i + 1,
+ m.group('owner')))
+
+
+def main():
+ result = 0
+ checker = Checker(sys.argv[1])
+ checker.run()
+ for entry in checker.log:
+ result = 1
+ print entry
+ sys.exit(result)
Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py 2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,63 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import os
+import re
+import shutil
+import subvertpy.client
+import subvertpy.ra
+import tempfile
+import zope.repositorypolicy.project
+
+
+RELEASE_BRANCH = re.compile(r'^[0-9]+\.[0-9]+$')
+
+
+class Checker(object):
+
+ root = 'svn://svn.zope.org/repos/main'
+
+ def __init__(self):
+ self.repos = subvertpy.ra.RemoteAccess(self.root)
+
+ def run(self):
+ for project, branch in self.list_projects_branches():
+ working_dir = tempfile.mkdtemp()
+ os.chdir(working_dir)
+ try:
+ c = subvertpy.client.Client()
+ c.checkout(url='%s/%s/%s' % (self.root, project, branch),
+ path=working_dir, rev='HEAD')
+ checker = zope.repositorypolicy.project.Checker(working_dir)
+ checker.run()
+ for entry in checker.log:
+ yield '%s/%s:%s' % (project, branch, entry)
+ finally:
+ shutil.rmtree(working_dir)
+
+ def list_projects_branches(self):
+ for project in self.repos.get_dir('/')[0].keys():
+ top = self.repos.get_dir(project)[0].keys()
+ if 'trunk' in top:
+ yield project, 'trunk'
+ if 'branches' in top:
+ branches = self.repos.get_dir(
+ '%s/branches' % project)[0].keys()
+ releases = []
+ for branch in branches:
+ if not RELEASE_BRANCH.match(branch):
+ continue
+ releases.append([int(x) for x in branch.split('.')])
+ releases.sort()
+ for release in releases[-2:]:
+ release = '.'.join(str(x) for x in release)
+ yield project, 'branches/%s' % release
+
+
+def main():
+ result = 0
+ checker = Checker()
+ for entry in checker.run():
+ result = 1
+ print entry
+ sys.exit(result)
Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py
___________________________________________________________________
Added: svn:eol-style
+ native
More information about the checkins
mailing list