From befa4c08503c1beebbf822450d88b1f5c026b9bc Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 9 Feb 2008 18:29:09 +0100 Subject: [PATCH 1/7] requestsync: Use debian_bundle.changelog.Version for version comparison in debian_changelog. Fixes cases where the current ubuntu version is not in debian anymore, e.g. p7zip-rar 4.55~ds.1-2 --- debian/changelog | 4 +++- requestsync | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index e358834..a18f57c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,8 +11,10 @@ ubuntu-dev-tools (0.26) UNRELEASED; urgency=low When interaction is not required, ask the user if she wants to edit. (LP: #190351) * Exit, if versions in Ubuntu and Debian are the same already. + * Use debian_bundle.changelog.Version for version comparison in + debian_changelog. - -- Daniel Hahler Sat, 09 Feb 2008 02:23:44 +0100 + -- Daniel Hahler Sat, 09 Feb 2008 18:27:06 +0100 ubuntu-dev-tools (0.25) hardy; urgency=low diff --git a/requestsync b/requestsync index be4a7ec..64d76e3 100755 --- a/requestsync +++ b/requestsync @@ -10,6 +10,7 @@ # License: GPLv2, see /usr/share/common-licenses/GPL import os, sys, urllib, subprocess, getopt +from debian_bundle.changelog import Version def cur_version_component(sourcepkg, release): '''Determine current package version in ubuntu.''' @@ -54,13 +55,17 @@ def debian_changelog(sourcepkg, component, version): '''Return the Debian changelog from the latest up to the given version (exclusive).''' + base_version = Version(version) + ch = '' subdir = sourcepkg[0] if sourcepkg.startswith('lib'): subdir = 'lib%s' % sourcepkg[3] for l in urllib.urlopen('http://packages.debian.org/changelogs/pool/%s/%s/%s/current/changelog.txt' % (component, subdir, sourcepkg)): - if l.startswith(sourcepkg) and l.find(version + ')') > 0: - break + if l.startswith(sourcepkg): + ch_version = l[ l.find("(")+1 : l.find(")") ] + if Version(ch_version) <= base_version: + break ch += l return ch From e9e8176b65c04c53c826e2538c43c837a25ad6f9 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 9 Feb 2008 18:51:14 +0100 Subject: [PATCH 2/7] Added myself to AUTHORS, debian/copyright --- AUTHORS | 1 + debian/copyright | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index d67b485..efee5f0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,6 @@ Albert Damen Albin Tonnerre +Daniel Hahler Daniel Holbach Jamin W. Collins Jordan Mantha diff --git a/debian/copyright b/debian/copyright index f8c14e1..07c6416 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,6 +4,7 @@ Fri, 01 Jun 2007 11:30:08 +0200. Upstream Author: Albert Damen Albin Tonnerre + Daniel Hahler Daniel Holbach Jamin W. Collins Jordan Mantha From 4600ff8981dc6d1605c7be6c0f0b0340749aa175 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 24 Feb 2008 19:59:14 +0100 Subject: [PATCH 3/7] Fix added newlines in report --- requestsync | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requestsync b/requestsync index 64d76e3..453a1ce 100755 --- a/requestsync +++ b/requestsync @@ -288,8 +288,8 @@ if __name__ == '__main__': else: subscribe = 'ubuntu-universe-sponsors' - report = 'Please sync %s %s (%s) from Debian unstable (%s).\n\n' % (srcpkg, deb_version, component, debiancomponent) - title = report[:-2] + report = 'Please sync %s %s (%s) from Debian unstable (%s).\n' % (srcpkg, deb_version, component, debiancomponent) + title = report[:-1] base_ver = cur_ver uidx = base_ver.find('ubuntu') @@ -301,8 +301,8 @@ if __name__ == '__main__': print 'Please edit the report and give an explanation.' print 'Press ENTER to start your editor. Press Control-C to abort now. Not saving the report file will abort the request, too.' wait_for_enter_or_exit() - report += '\nExplanation of the Ubuntu delta and why it can be dropped:\n\n' + \ - 'ENTER_EXPLANATION_HERE\n\n' + report += '\nExplanation of the Ubuntu delta and why it can be dropped:\n' + \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n\n' uidx = base_ver.find('build') if uidx > 0: From 6eba68a20dfbdbd96afbb2354056c89a1def9363 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 16 Apr 2008 02:05:58 +0200 Subject: [PATCH 4/7] requestsync: - Fix --lp for Firefox 3: it now tries ~/.lpcookie.txt, ~/.mozilla/*/*/cookies.sqlite and ~/.mozilla/*/*/cookies.txt to find a Launchpad cookie file - Added confirm loops, which displays the message to be send/posted and either allows to edit (or forces to, in case of Ubuntu changes). (LP: #194613, #194615) This adds a convient edit_report method, which gets used both from the Launchpad and mail code path. - Do not fallback to submitting by email, if posting to Launchpad failed. This hasn't been requested and therefore should not get done. --- debian/changelog | 20 ++++- requestsync | 194 +++++++++++++++++++++++++++++++---------------- 2 files changed, 148 insertions(+), 66 deletions(-) diff --git a/debian/changelog b/debian/changelog index a18f57c..eb6e38a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,21 @@ +ubuntu-dev-tools (0.31) hardy; urgency=low + + * requestsync: + - Use debian_bundle.changelog.Version for version comparison in + debian_changelog. + - Fix --lp for Firefox 3: it now tries ~/.lpcookie.txt, + ~/.mozilla/*/*/cookies.sqlite and ~/.mozilla/*/*/cookies.txt to find + a Launchpad cookie file + - Added confirm loops, which displays the message to be send/posted and + either allows to edit (or forces to, in case of Ubuntu changes). + (LP: #194613, #194615) + This adds a convient edit_report method, which gets used both from the + Launchpad and mail code path. + - Do not fallback to submitting by email, if posting to Launchpad failed. + This hasn't been requested and therefore should not get done. + + -- Daniel Hahler Wed, 16 Apr 2008 01:57:41 +0200 + ubuntu-dev-tools (0.26) UNRELEASED; urgency=low [ Stephan Hermann ] @@ -11,8 +29,6 @@ ubuntu-dev-tools (0.26) UNRELEASED; urgency=low When interaction is not required, ask the user if she wants to edit. (LP: #190351) * Exit, if versions in Ubuntu and Debian are the same already. - * Use debian_bundle.changelog.Version for version comparison in - debian_changelog. -- Daniel Hahler Sat, 09 Feb 2008 18:27:06 +0100 diff --git a/requestsync b/requestsync index 453a1ce..af8dc55 100755 --- a/requestsync +++ b/requestsync @@ -12,6 +12,15 @@ import os, sys, urllib, subprocess, getopt from debian_bundle.changelog import Version +# Set this to the path of your Launchpad cookie file, when using +# python-launchpad-bugs support (--lp). +# The following will be tried automatically, if unset (first match gets used): +# 1. ~/.lpcookie.txt +# 2. ~/.mozilla/*/*/cookies.sqlite +# 3. ~/.mozilla/*/*/cookies.txt +launchpad_cookiefile = None + + def cur_version_component(sourcepkg, release): '''Determine current package version in ubuntu.''' madison = subprocess.Popen(['rmadison', '-u', 'ubuntu', '-a', 'source', \ @@ -88,10 +97,10 @@ def debian_component(sourcepkg): component = raw_comp[1].strip() return component -def wait_for_enter_or_exit(): - """Helper function to wait for ENTER and catch Control-C for abortion.""" +def raw_input_exit_on_ctrlc(*args, **kwargs): + """A wrapper around raw_input() to exit with a normalized message on Control-C""" try: - raw_input() + return raw_input(*args, **kwargs) except KeyboardInterrupt: print 'Abort requested. No sync request filed.' sys.exit(1) @@ -125,6 +134,7 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) print >> sys.stderr, 'The environment variable DEBEMAIL needs to be set to make use of this script.' return False + # generate initial mailbody: mailbody = '' if source_package: mailbody += ' affects ubuntu/%s\n' % source_package @@ -132,7 +142,7 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) mailbody += ' affects ubuntu\n' mailbody = mailbody + ' status %s\n importance wishlist\n subscribe %s\n\n%s' % (status, subscribe, bugtext) - # sign it + # prepare sign_command: sign_command = 'gpg' for cmd in ('gpg2', 'gnome-gpg'): if os.access('/usr/bin/%s' % cmd, os.X_OK): @@ -142,17 +152,29 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) if keyid: gpg_command.extend(('-u', keyid)) - gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) - signed_report = gpg.communicate(mailbody)[0] - assert gpg.returncode == 0 + in_confirm_loop = True + while in_confirm_loop: + # sign it + gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + signed_report = gpg.communicate(mailbody)[0] + assert gpg.returncode == 0 - # generate email - mail = 'From: %s\nTo: %s\nSubject: %s\n\n%s' % (myemailaddr, to, bugtitle, signed_report) + # generate email + mail = 'From: %s\nTo: %s\nSubject: %s\n\n%s' % (myemailaddr, to, bugtitle, signed_report) - print mail - - print 'Press ENTER to file this bug, Control-C to abort.' - wait_for_enter_or_exit() + # ask for confirmation and allow to edit: + print mail + print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' + while 1: + val = raw_input_exit_on_ctrlc() + if val.lower() in ('y', 'yes'): + (bugtitle, mailbody) = edit_report(bugtitle, mailbody) + break + elif val.lower() in ('n', 'no', ''): + in_confirm_loop = False + break + else: + print "Invalid answer" # get server address mailserver = os.getenv('DEBSMTP') @@ -194,23 +216,33 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) def post_bug(source_package, subscribe, status, bugtitle, bugtext): '''Use python-launchpad-bugs to submit the sync request. - Return True if email successfully send, otherwise False.''' + Return True if successfully posted, otherwise False.''' import glob, os.path + global launchpad_cookiefile try: import launchpadbugs.connector except ImportError: print >> sys.stderr, 'Importing launchpadbugs failed. Is python-launchpad-bugs installed?' - print >> sys.stderr, 'Falling back to submitting per email.' return False # Search cookiefile (for authentication to lp) - try: - cookiefile = glob.glob(os.path.expanduser('~/.mozilla/*/*/cookies.txt'))[0] - except IndexError: - print >> sys.stderr, 'Could not find Firefox cookie file' - return False + if launchpad_cookiefile == None: + try_globs = ('~/.lpcookie.txt', '~/.mozilla/*/*/cookies.sqlite', '~/.mozilla/*/*/cookies.txt') + for try_glob in try_globs: + try: + cookiefile = glob.glob(os.path.expanduser(try_glob))[0] + except IndexError: + continue + # Found: + launchpad_cookiefile = cookiefile + print "Using cookie file at %s" % launchpad_cookiefile + break + + if launchpad_cookiefile == None: + print >> sys.stderr, 'Could not find cookie file for Launchpad (looked in %s)' % ", ".join(try_globs) + return False if source_package: product = {'name': source_package, 'target': 'ubuntu'} @@ -218,14 +250,26 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): # new source package product = {'name': 'ubuntu'} - print 'Summary:\n%s\n\nDescription:\n%s' % (bugtitle, bugtext) + in_confirm_loop = True + while in_confirm_loop: + print 'Summary:\n%s\n\nDescription:\n%s' % (bugtitle, bugtext) - print 'Press ENTER to file this bug, Control-C to abort.' - wait_for_enter_or_exit() + # ask for confirmation and allow to edit: + print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' + while 1: + val = raw_input_exit_on_ctrlc() + if val.lower() in ('y', 'yes'): + (bugtitle, bugtext) = edit_report(bugtitle, bugtext) + break + elif val.lower() in ('n', 'no', ''): + in_confirm_loop = False + break + else: + print "Invalid answer" # Create bug Bug = launchpadbugs.connector.ConnectBug() - Bug.authentication = cookiefile + Bug.authentication = launchpad_cookiefile bug = Bug.New(product = product, summary = bugtitle, description = bugtext) bug.importance = 'Wishlist' @@ -237,6 +281,54 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): return True +def edit_report(subject, body, changes_required=False): + """Edit a report (consisting of subject and body) in sensible-editor. + + subject and body get decorated, before they are written to the temporary + file and undecorated after editing again. + If changes_required is True and the file has not been edited + (according to its mtime), an error is written to STDERR and the + program exits. + Returns (new_subject, new_body). + """ + import re, string + + report = "Summary (one line):\n%s\n\nDescription:\n%s" % (subject, body) + + # Create tempfile and remember mtime + import tempfile + report_file = tempfile.NamedTemporaryFile( prefix='requestsync_' ) + report_file.file.write(report) + report_file.file.flush() + mtime_before = os.stat( report_file.name ).st_mtime + + # Launch editor + try: + editor = subprocess.check_call( ['sensible-editor', report_file.name] ) + except subprocess.CalledProcessError, e: + print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % (e,) + sys.exit(1) + + # Check if the tempfile has been changed + if changes_required: + report_file_info = os.stat( report_file.name ) + if mtime_before == os.stat( report_file.name ).st_mtime: + print >> sys.stderr, 'The temporary file %s has not been changed, but you have\nto explain why the Ubuntu changes can be dropped. Aborting. [Press ENTER]' % (report_file.name,) + raw_input() + sys.exit(1) + + report_file.file.seek(0) + report = report_file.file.read() + report_file.file.close() + + # Undecorate report again: + (new_subject, new_body) = report.split("\nDescription:\n", 1) + # Remove prefix and whitespace for subject: + new_subject = string.rstrip( re.sub("\n", " ", re.sub("^Summary \(one line\):\s*", "", new_subject, 1)) ) + + return (new_subject, new_body) + + # # entry point # @@ -247,7 +339,6 @@ if __name__ == '__main__': keyid = None use_lp_bugs = False need_interaction = False - edit_report = False try: opts, args = getopt.gnu_getopt(sys.argv[1:], 'hnsk:', ('lp')) @@ -288,8 +379,8 @@ if __name__ == '__main__': else: subscribe = 'ubuntu-universe-sponsors' - report = 'Please sync %s %s (%s) from Debian unstable (%s).\n' % (srcpkg, deb_version, component, debiancomponent) - title = report[:-1] + report = 'Please sync %s %s (%s) from Debian unstable (%s).\n\n' % (srcpkg, deb_version, component, debiancomponent) + title = report[:-2] base_ver = cur_ver uidx = base_ver.find('ubuntu') @@ -297,12 +388,13 @@ if __name__ == '__main__': base_ver = base_ver[:uidx] need_interaction = True - print 'There have been changes made in Ubuntu.' + print 'Changes have been made to the package in Ubuntu.' print 'Please edit the report and give an explanation.' - print 'Press ENTER to start your editor. Press Control-C to abort now. Not saving the report file will abort the request, too.' - wait_for_enter_or_exit() - report += '\nExplanation of the Ubuntu delta and why it can be dropped:\n' + \ - '>>> ENTER_EXPLANATION_HERE <<<\n\n\n' + print 'Press ENTER to start your editor. Press Control-C to abort now.' + print 'Not saving the report file will abort the request, too.' + raw_input_exit_on_ctrlc() + report += 'Explanation of the Ubuntu delta and why it can be dropped:\n' + \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n' uidx = base_ver.find('build') if uidx > 0: @@ -314,47 +406,21 @@ if __name__ == '__main__': report += 'Changelog since current %s version %s:\n\n' % (release, cur_ver) report += debian_changelog(srcpkg, debiancomponent, base_ver) + '\n' - # Do we want to edit the report? if need_interaction: - edit_report = True - else: - val = raw_input('Do you want to edit the report [y/N]? ') - if val.lower() in ('y', 'yes'): - edit_report = True + report = edit_report(title, report, changes_required=True) - if edit_report: - # Create tempfile and remember mtime - import tempfile - report_file = tempfile.NamedTemporaryFile( prefix='requestsync_' ) - report_file.file.write(report) - report_file.file.flush() - mtime_before = os.stat( report_file.name ).st_mtime - - # Launch editor - try: - editor = subprocess.check_call( ['sensible-editor', report_file.name] ) - except subprocess.CalledProcessError, e: - print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % (e,) - sys.exit(1) - - # Check if the tempfile has been changed - report_file_info = os.stat( report_file.name ) - if mtime_before == os.stat( report_file.name ).st_mtime: - print >> sys.stderr, 'The temporary file %s has not been changed. Aborting. [Press ENTER]' % (report_file.name,) - raw_input() - sys.exit(1) - report_file.file.seek(0) - report = report_file.file.read() - report_file.file.close() - - # mail or post the sync request + # Post sync request using Launchpad interface: srcpkg = not newsource and srcpkg or None if use_lp_bugs: # Map status to the values expected by lp-bugs mapping = {'new': 'New', 'confirmed': 'Confirmed'} if post_bug(srcpkg, subscribe, mapping[status], title, report): sys.exit(0) + # Abort on error: + print 'Something went wrong. No sync request filed.' + sys.exit(1) + # Mail sync request: if mail_bug(srcpkg, subscribe, status, title, report, keyid): sys.exit(0) From fd5479e548588f7d86cc7e79dee47c52680919a4 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 16 Apr 2008 02:14:55 +0200 Subject: [PATCH 5/7] requestsync: - post_bug: Catch IOError when setting bug importance (LP: #190061) - Added myself to list of authors --- debian/changelog | 1 + requestsync | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index eb6e38a..29ff599 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,7 @@ ubuntu-dev-tools (0.31) hardy; urgency=low Launchpad and mail code path. - Do not fallback to submitting by email, if posting to Launchpad failed. This hasn't been requested and therefore should not get done. + - post_bug: Catch IOError when setting bug importance (LP: #190061) -- Daniel Hahler Wed, 16 Apr 2008 01:57:41 +0200 diff --git a/requestsync b/requestsync index af8dc55..89b329b 100755 --- a/requestsync +++ b/requestsync @@ -6,6 +6,7 @@ # Martin Pitt # Steve Kowalik # Michael Bienia (python-launchpad-bugs support) +# Daniel Hahler (http://daniel.hahler.de/) # # License: GPLv2, see /usr/share/common-licenses/GPL @@ -272,7 +273,10 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): Bug.authentication = launchpad_cookiefile bug = Bug.New(product = product, summary = bugtitle, description = bugtext) - bug.importance = 'Wishlist' + try: + bug.importance = 'Wishlist' + except IOError, s: + print "Warning: setting importance failed: %s" % s bug.status = status bug.subscriptions.add(subscribe) bug.commit() From 3f7c03a0e89fd6c6ae449e872e91491d8e5c51c6 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 16 Apr 2008 02:25:33 +0200 Subject: [PATCH 6/7] requestsync: mail_bug: Catch socket.error (LP: #190739) --- debian/changelog | 1 + requestsync | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 29ff599..4f2cfee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,7 @@ ubuntu-dev-tools (0.31) hardy; urgency=low - Do not fallback to submitting by email, if posting to Launchpad failed. This hasn't been requested and therefore should not get done. - post_bug: Catch IOError when setting bug importance (LP: #190061) + - mail_bug: Catch socket.error (LP: #190739) -- Daniel Hahler Wed, 16 Apr 2008 01:57:41 +0200 diff --git a/requestsync b/requestsync index 89b329b..f8b583f 100755 --- a/requestsync +++ b/requestsync @@ -127,6 +127,7 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) Return True if email successfully send, otherwise False.''' import smtplib + import socket to = 'new@bugs.launchpad.net' @@ -192,7 +193,12 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) mailserver_port = 25 # connect to the server - s = smtplib.SMTP(mailserver, mailserver_port) + try: + s = smtplib.SMTP(mailserver, mailserver_port) + except socket.error, s: + print "ERROR: Could not connect to mailserver %s at port %s: %s (%i)" % \ + (mailserver, mailserver_port, s[1], s[0]) + return False # authenticate to the server mailserver_user = os.getenv('DEBSMTP_USER') From a736d68653ef4c409d48b5d29268ada497b8ccc5 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 16 Apr 2008 02:30:01 +0200 Subject: [PATCH 7/7] requestsync: Add hint about how to create a valid cookie file (Firefox) --- debian/changelog | 8 +++++--- requestsync | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4f2cfee..4a211d7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,9 +3,11 @@ ubuntu-dev-tools (0.31) hardy; urgency=low * requestsync: - Use debian_bundle.changelog.Version for version comparison in debian_changelog. - - Fix --lp for Firefox 3: it now tries ~/.lpcookie.txt, - ~/.mozilla/*/*/cookies.sqlite and ~/.mozilla/*/*/cookies.txt to find - a Launchpad cookie file + - Fix --lp for Firefox 3 (LP: 208808): + It now tries ~/.lpcookie.txt, ~/.mozilla/*/*/cookies.sqlite and + ~/.mozilla/*/*/cookies.txt to find a Launchpad cookie file. + Also added a hint that you can create a valid file, by logging into + Launchpad with Firefox. - Added confirm loops, which displays the message to be send/posted and either allows to edit (or forces to, in case of Ubuntu changes). (LP: #194613, #194615) diff --git a/requestsync b/requestsync index f8b583f..d1334d4 100755 --- a/requestsync +++ b/requestsync @@ -249,6 +249,7 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): if launchpad_cookiefile == None: print >> sys.stderr, 'Could not find cookie file for Launchpad (looked in %s)' % ", ".join(try_globs) + print >> sys.stderr, 'You should be able to create a valid file by logging into Launchpad with Firefox' return False if source_package: