Created
January 9, 2013 19:58
-
-
Save esteele/4496309 to your computer and use it in GitHub Desktop.
The start of my buildout extension for managing Plone releases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/Users/ems174/projects/env/plone_4.3/bin/python | |
from argh import ArghParser, command | |
from configparser import ConfigParser, ExtendedInterpolation, NoOptionError | |
import xmlrpclib | |
import git | |
from shutil import rmtree | |
from tempfile import mkdtemp | |
from collections import OrderedDict | |
def getVersion(package_name): | |
config = ConfigParser(interpolation=ExtendedInterpolation()) | |
config.readfp(open('versions.cfg')) | |
version = config.get('versions', package_name) | |
return version | |
def getAutoCheckouts(): | |
config = ConfigParser(interpolation=ExtendedInterpolation()) | |
config.readfp(open('checkouts.cfg')) | |
checkouts = config.get('buildout', 'auto-checkout') | |
checkout_list = checkouts.split('\n') | |
return checkout_list | |
def setAutoCheckouts(checkouts_list): | |
config = ConfigParser(interpolation=ExtendedInterpolation()) | |
config.readfp(open('checkouts.cfg')) | |
checkouts = '\n'.join(checkouts_list) | |
config.set('buildout', 'auto-checkout', checkouts) | |
config.write(open('checkouts.cfg', 'w')) | |
def getSourcesConfig(): | |
config = ConfigParser(interpolation=ExtendedInterpolation()) | |
config.optionxform = str | |
config.readfp(open('sources.cfg')) | |
return config | |
class Source(): | |
def __init__(self, protocol=None, url=None, push_url=None, branch=None): | |
self.protocol = protocol | |
self.url = url | |
self.push_url = push_url | |
self.branch = branch | |
def create_from_string(self, source_string): | |
protocol, url, push_url, branch = (lambda a, b, c=None, d=None: (a, b, c, d))(*source_string.split()) | |
self.protocol = protocol | |
self.url = url | |
if push_url is not None: | |
self.push_url = push_url.split('=')[-1] | |
if branch is None: | |
self.branch = 'master' | |
else: | |
self.branch = branch.split('=')[-1] | |
return self | |
def getSources(): | |
config = getSourcesConfig() | |
sources_dict = OrderedDict() | |
for name, value in config['sources'].items(): | |
source = Source().create_from_string(value) | |
sources_dict[name] = source | |
return sources_dict | |
def getSource(package_name): | |
config = getSourcesConfig() | |
source = Source().create_from_string(config.get('sources', package_name)) | |
return source | |
def addToCheckouts(package_name): | |
checkouts = getAutoCheckouts() | |
checkouts.append(package_name) | |
setAutoCheckouts(checkouts) | |
def removeFromCheckouts(package_name): | |
checkouts = getAutoCheckouts() | |
checkouts.remove(package_name) | |
setAutoCheckouts(checkouts) | |
def setVersion(package_name, new_version): | |
import configparser | |
versions = ConfigParser(interpolation=ExtendedInterpolation()) | |
versions.optionxform = str | |
versions_file = open('versions.cfg') | |
versions.readfp(versions_file) | |
# versions.set('versions', package_name, new_version) | |
# versions.write(open('versions.cfg', 'w')) | |
@command | |
def release(package, new_version): | |
# Remove from checkouts | |
# removeFromCheckouts(package) | |
# Update version number | |
setVersion(package, new_version) | |
print package, new_version | |
THIRD_PARTY_PACKAGES= ['Zope2', | |
'ZODB3', | |
'txtfilter', | |
'Products.CMFActionIcons', | |
'Products.CMFCalendar', | |
'Products.CMFCore', | |
'Products.CMFDefault', | |
'Products.CMFTopic', | |
'Products.CMFUid', | |
'Products.DCWorkflow', | |
'Products.GenericSetup', | |
'Products.GroupUserFolder', | |
'Products.PluggableAuthService', | |
'Products.PluginRegistry', | |
'Products.ZCatalog'] | |
@command | |
def checkPypi(user): | |
config = getSourcesConfig() | |
client = xmlrpclib.ServerProxy('http://pypi.python.org/pypi') | |
my_pacakges = [package for role, package in client.user_packages(user)] | |
for package in config.options('sources'): | |
if package not in my_pacakges and package not in THIRD_PARTY_PACKAGES: | |
existing_admins = [user for role, user in client.package_roles(package)] | |
print package, existing_admins | |
@command | |
def checkPackageForUpdates(package_name): | |
source = getSource(package_name) | |
checkouts = getAutoCheckouts() | |
try: | |
version = getVersion(package_name) | |
except NoOptionError: | |
# print "No version available for %s" % package_name | |
pass | |
else: | |
if source.protocol == 'git': | |
tmpdir = mkdtemp() | |
# print "Reading %s branch of %s for changes since %s..." % (source.branch, package_name, version) | |
repo = git.Repo.clone_from(source.url, tmpdir, branch=source.branch) | |
g = git.Git(tmpdir) | |
try: | |
latest_tag_in_branch = g.describe('--abbrev=0', '--tags') | |
except git.exc.GitCommandError: | |
# print "Unable to check tags for %s" % package_name | |
pass | |
else: | |
if latest_tag_in_branch > version: | |
print "Newer version %s is available for %s." % (latest_tag_in_branch, package_name) | |
return | |
commits_since_release = list(repo.iter_commits('%s..%s' % (version, source.branch))) | |
if not commits_since_release\ | |
or "Back to development" in commits_since_release[0].message\ | |
or commits_since_release[0].message.startswith('vb'): | |
# print "No changes." | |
pass | |
else: | |
print "\n" | |
# Check for checkout | |
if package_name not in checkouts: | |
print "No auto-checkout exists for %s" % package_name | |
print "Changes in %s:" % package_name | |
for commit in commits_since_release: | |
print " %s: %s" % (commit.author, commit.summary) | |
rmtree(tmpdir) | |
else: | |
# print "Skipped check of %s as it's not a git repo." % package_name | |
pass | |
@command | |
def checkAllPackagesForUpdates(): | |
sources = getSources() | |
for package_name in sources: | |
checkPackageForUpdates(package_name) | |
# print "\n" | |
parser = ArghParser() | |
parser.add_commands([release, checkPypi, checkPackageForUpdates, checkAllPackagesForUpdates]) | |
if __name__ == '__main__': | |
parser.dispatch() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment