2009-09-05 16:40:10 +02:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
# Copyright (c) 2009 Canonical Ltd.
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
|
|
# under the terms of the GNU General Public License as published by the
|
|
|
|
# Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
# later version.
|
|
|
|
#
|
2010-09-21 17:42:04 +02:00
|
|
|
# lp-project-upload is distributed in the hope that it will be useful, but
|
2009-09-05 16:40:10 +02:00
|
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
# General Public License for more details.
|
|
|
|
|
|
|
|
# Authors:
|
|
|
|
# Martin Pitt <martin.pitt@ubuntu.com>, based on
|
|
|
|
# http://blog.launchpad.net/api/recipe-for-uploading-files-via-the-api
|
2011-06-02 18:30:20 -04:00
|
|
|
# Dustin Kirkland <kirkland@ubuntu.com>
|
|
|
|
# - support files for changelog and release notes
|
2009-09-05 16:40:10 +02:00
|
|
|
|
|
|
|
'''Upload a release tarball to a Launchpad project.'''
|
|
|
|
|
2010-12-27 21:54:31 +01:00
|
|
|
import datetime
|
|
|
|
import os
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import tempfile
|
2009-09-05 16:40:10 +02:00
|
|
|
|
2011-03-01 00:30:54 +02:00
|
|
|
from launchpadlib.launchpad import Launchpad
|
2009-09-05 16:40:10 +02:00
|
|
|
from launchpadlib.errors import HTTPError
|
|
|
|
|
|
|
|
def create_release(project, version):
|
|
|
|
'''Create new release and milestone for LP project.'''
|
|
|
|
|
2010-12-27 14:21:01 +01:00
|
|
|
print 'Release %s could not be found for project. Create it? (Y/n)' % \
|
|
|
|
version
|
2009-09-05 16:40:10 +02:00
|
|
|
answer = sys.stdin.readline().strip()
|
|
|
|
if answer.startswith('n'):
|
|
|
|
sys.exit(0)
|
2010-09-22 14:45:00 -03:00
|
|
|
|
2010-12-27 21:54:31 +01:00
|
|
|
n_series = len(project.series)
|
2010-09-22 14:45:00 -03:00
|
|
|
if n_series == 1:
|
2010-12-27 21:54:31 +01:00
|
|
|
series = project.series[0]
|
2010-09-22 14:45:00 -03:00
|
|
|
elif n_series > 1:
|
|
|
|
msg = 'More than one series exist. Which one would you like to ' \
|
|
|
|
'upload to? Possible series are (listed as index, name):'
|
|
|
|
print msg
|
2010-12-27 21:54:31 +01:00
|
|
|
for idx, serie in enumerate(project.series):
|
2010-09-22 14:45:00 -03:00
|
|
|
print '\t%i - %s' % (idx, serie.name)
|
|
|
|
print 'Enter series index: '
|
|
|
|
answer = sys.stdin.readline().strip()
|
|
|
|
try:
|
2010-12-27 21:54:31 +01:00
|
|
|
series = project.series[int(answer)]
|
2010-09-22 14:45:00 -03:00
|
|
|
except (ValueError, IndexError):
|
|
|
|
print >> sys.stderr, 'The series index is invalid (%s).' % answer
|
|
|
|
sys.exit(3)
|
|
|
|
else:
|
|
|
|
print "Using series named '%s'" % series.name
|
|
|
|
else:
|
2010-12-27 14:21:01 +01:00
|
|
|
print >> sys.stderr, ('Does not support creating releases if no '
|
|
|
|
'series exists.')
|
2009-09-05 16:40:10 +02:00
|
|
|
sys.exit(3)
|
2010-09-22 14:45:00 -03:00
|
|
|
|
2009-09-05 16:40:10 +02:00
|
|
|
release_date = datetime.date.today().strftime('%Y-%m-%d')
|
|
|
|
milestone = series.newMilestone(name=version,
|
|
|
|
date_targeted=release_date)
|
|
|
|
return milestone.createProductRelease(date_released=release_date)
|
|
|
|
|
2009-11-20 16:59:00 -06:00
|
|
|
def edit_file(prefix, description):
|
|
|
|
(fd, f) = tempfile.mkstemp(prefix=prefix+'.')
|
2010-12-27 14:21:01 +01:00
|
|
|
os.write(fd, '\n\n#------\n# Please enter the %s here. '
|
|
|
|
'Lines which start with "#" are ignored.\n' % description)
|
2009-11-20 16:59:00 -06:00
|
|
|
os.close(fd)
|
|
|
|
subprocess.call(['sensible-editor', f])
|
2011-06-02 18:30:20 -04:00
|
|
|
return cat_file(f)
|
|
|
|
|
|
|
|
def cat_file(f):
|
2009-11-20 16:59:00 -06:00
|
|
|
content = ''
|
2010-12-27 21:54:31 +01:00
|
|
|
for line in open(f):
|
|
|
|
if line.startswith('#'):
|
2009-11-20 16:59:00 -06:00
|
|
|
continue
|
2010-12-27 21:54:31 +01:00
|
|
|
content += line
|
2009-11-20 16:59:00 -06:00
|
|
|
return content.strip()
|
|
|
|
|
2010-12-27 21:54:31 +01:00
|
|
|
def main():
|
2011-06-02 18:30:20 -04:00
|
|
|
if len(sys.argv) < 4 or len(sys.argv) > 7:
|
2010-12-27 21:54:31 +01:00
|
|
|
print >> sys.stderr, '''Upload a release tarball to a Launchpad project.
|
|
|
|
|
2011-06-02 18:30:20 -04:00
|
|
|
Usage: %s <project name> <version> <tarball> [new milestone] [changelog file] [releasenotes file]''' % sys.argv[0]
|
2010-12-27 21:54:31 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
2011-06-09 13:36:06 +02:00
|
|
|
new_milestone = None
|
2011-06-02 18:30:20 -04:00
|
|
|
changelog_file = None
|
|
|
|
releasenotes_file = None
|
2011-03-23 22:03:54 -05:00
|
|
|
if len(sys.argv) == 4:
|
|
|
|
(project, version, tarball) = sys.argv[1:]
|
2011-06-02 18:30:20 -04:00
|
|
|
elif len(sys.argv) == 5:
|
2011-03-23 22:03:54 -05:00
|
|
|
(project, version, tarball, new_milestone) = sys.argv[1:]
|
2011-06-02 18:30:20 -04:00
|
|
|
elif len(sys.argv) == 6:
|
|
|
|
(project, version, tarball, new_milestone, changelog_file) = sys.argv[1:]
|
|
|
|
elif len(sys.argv) == 7:
|
|
|
|
(project, version, tarball, new_milestone, changelog_file, releasenotes_file) = sys.argv[1:]
|
2010-12-27 21:54:31 +01:00
|
|
|
|
|
|
|
try:
|
2011-03-01 00:30:54 +02:00
|
|
|
launchpad = Launchpad.login_with('ubuntu-dev-tools', 'production')
|
2010-12-27 21:54:31 +01:00
|
|
|
except Exception, error:
|
|
|
|
print >> sys.stderr, 'Could not connect to Launchpad:', str(error)
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
try:
|
|
|
|
# Look up the project using the Launchpad instance.
|
|
|
|
proj = launchpad.projects[project]
|
|
|
|
# Find the release in the project's releases collection.
|
|
|
|
release = None
|
|
|
|
for rel in proj.releases:
|
|
|
|
if rel.version == version:
|
|
|
|
release = rel
|
|
|
|
break
|
2011-03-23 13:49:49 -05:00
|
|
|
if not release:
|
|
|
|
for milestone in proj.all_milestones:
|
|
|
|
if milestone.name == version:
|
2011-03-23 20:52:16 -05:00
|
|
|
today = datetime.date.today().strftime('%Y-%m-%d')
|
|
|
|
release = milestone.createProductRelease(date_released=today)
|
2010-12-27 21:54:31 +01:00
|
|
|
if not release:
|
|
|
|
release = create_release(proj, version)
|
|
|
|
|
|
|
|
# Get the file contents.
|
|
|
|
file_content = open(tarball, 'r').read()
|
|
|
|
# Get the signature, if available.
|
|
|
|
signature = tarball + '.asc'
|
|
|
|
if not os.path.exists(signature):
|
|
|
|
print 'Calling GPG to create tarball signature...'
|
|
|
|
cmd = ['gpg', '--armor', '--sign', '--detach-sig', tarball]
|
|
|
|
if subprocess.call(cmd) != 0:
|
|
|
|
print >> sys.stderr, 'gpg failed, aborting'
|
|
|
|
|
|
|
|
if os.path.exists(signature):
|
|
|
|
signature_content = open(signature, 'r').read()
|
|
|
|
else:
|
|
|
|
signature_content = None
|
|
|
|
|
|
|
|
# Create a new product release file.
|
|
|
|
filename = os.path.basename(tarball)
|
|
|
|
release.add_file(filename=filename, description='release tarball',
|
|
|
|
file_content=file_content, content_type='appplication/x-gzip',
|
|
|
|
file_type='Code Release Tarball', signature_filename=signature,
|
|
|
|
signature_content=signature_content)
|
|
|
|
|
2011-06-02 18:30:20 -04:00
|
|
|
if changelog_file is not None:
|
|
|
|
changelog = cat_file(changelog_file)
|
|
|
|
else:
|
|
|
|
changelog = edit_file('changelog', 'changelog')
|
2010-12-27 21:54:31 +01:00
|
|
|
if changelog:
|
|
|
|
release.changelog = changelog
|
2011-06-02 18:30:20 -04:00
|
|
|
|
|
|
|
if releasenotes_file is not None:
|
|
|
|
release_notes = cat_file(releasenotes_file)
|
|
|
|
else:
|
|
|
|
release_notes = edit_file('releasenotes', 'release notes')
|
2010-12-27 21:54:31 +01:00
|
|
|
if release_notes:
|
|
|
|
release.release_notes = release_notes
|
|
|
|
|
|
|
|
release.lp_save()
|
|
|
|
|
2011-03-23 22:02:43 -05:00
|
|
|
# Create a new milestone if requested
|
2011-04-15 16:35:54 -05:00
|
|
|
if new_milestone is not None:
|
2011-03-23 17:07:00 -05:00
|
|
|
mil = release.milestone
|
|
|
|
for series in proj.series:
|
2011-03-24 09:57:18 -05:00
|
|
|
if mil.name in [milestone.name for milestone in series.all_milestones]:
|
|
|
|
series.newMilestone(name=new_milestone)
|
2011-03-23 17:06:39 -05:00
|
|
|
|
2010-12-27 21:54:31 +01:00
|
|
|
except HTTPError, error:
|
|
|
|
print 'An error happened in the upload:', error.content
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|