#!/usr/bin/python # # Copyright 2007, Canonical, Daniel Holbach # # GPL 3 # # # Notes: # - needs dput, python-launchpad-bugs (>= 0.2.14) # - needs http://launchpad.net/bugs/137767 to get fixed # # # 11:57:27 < dholbach> but what it does is: build a source package of # the current source tree you're in, upload it to PPA # and follow up on a bug report, subscribe the right # sponsors, set the right status - if you pass "-n" # it will file a bug report, add a (LP: #....) to # the changelog also # 11:57:37 < dholbach> I thought it'd help with our sponsoring process # import re import os import sys import string try: import launchpadbugs.connector as Connector except: print >> sys.stderr, \ "You need python-launchpad-bugs (>= 0.2.14) installed to use revuput." sys.exit(1) #try: # import apt #except: # print >> sys.stderr, "You need python-apt installed to use revuput." # sys.exit(1) USAGE = \ """Usage: revuput [-n] [] [] -n to file a new bug dput alias options that are passed to debuild(1) """ def dput_check(): if not os.path.exists("/usr/bin/dput"): print >> sys.stderr, "You need to install the dput package." sys.exit(1) def find_fixed_launchpad_bug(changesfile): changes = open(changesfile).readlines() for line in changes: if line.startswith("Launchpad-Bugs-Fixed"): return line.split(":")[1].split() return [] def call_dput(location, changes): dput_check() incoming = "" res = False (dummy, output, dummy) = os.popen3("dput --debug %s %s" % (location, changes)) text = output.readlines() for line in text: if line.startswith("D: Incoming: "): incoming = line.split("D: Incoming: ")[1].strip() if incoming[-1] == "/": incoming = incoming[:-1] if line.startswith("Successfully uploaded packages."): res = True return (res, incoming) def lookup_dput_host(host): dput_check() (dummy, output, dummy) = os.popen3("dput -H | grep ^%s" % host) text = output.read() if text: return text.split()[2] return "" def call_debuild(options): # FIXME: this requires magic, that figures out when to use --native --working, # etc. # if os.path.exists(".bzr") and os.path.exists("/usr/bin/bzr-buildpackage"): # return os.system("bzr bd -S --builder='-k%s %s'" % \ # (os.getenv("DEBEMAIL"), \ # string.join(options, " "))) == 0 # else: return os.system("debuild -S -k%s %s" % \ (os.getenv("DEBEMAIL"), \ string.join(options, " "))) == 0 def get_name_and_version(): changelogfile = "debian/changelog" if not os.path.exists(changelogfile): print >> sys.stderr, "%s not found." % changelogfile sys.exit(1) head = open(changelogfile).readline() return re.findall(r'^(.*)\ \((.*)\).*', head) def assemble_bug_comment_text(host, incoming, sourcepackage, version): if host == "ppa.launchpad.net": dsc_file_location = "http://%s/%s/pool/main/%s/%s/%s_%s.dsc" % \ (host, incoming[1:], sourcepackage[0], sourcepackage, \ sourcepackage, version) else: # FIXME: this needs to be much much cleverer at some stage dsc_file_location = "http://%s/%s/pool/main/%s/%s/%s_%s.dsc" % \ (host, incoming, sourcepackage[0], sourcepackage, version) return """A new version of %s was uploaded to fix this bug. To review the current version, please run dget -x %s """ % (sourcepackage, dsc_file_location) def deal_with_bugreport(bugnumbers, host, incoming, sourcepackage, version): if not os.path.exists(os.path.expanduser("~/.lpcookie")): print >> sys.stderr, \ "You need your Launchpad Cookie to be stored in ~/.lpcookie" sys.exit(1) #print apt.Cache()[sourcepackage].section.split("/")[0].count("verse") (dummy, output, dummy) = os.popen3( "apt-cache showsrc %s | grep Directory | cut -d' ' -f2 | cut -d'/' -f2" % \ sourcepackage) component = output.read().strip() Bug = Connector.ConnectBug() Bug.authentication = os.path.expanduser("~/.lpcookie") for bugnumber in bugnumbers: bug = Bug(int(bugnumber)) if component in ["main", "restricted"] and \ 'ubuntu-main-sponsors' not in [str(s) for s in bug.subscribers]: bug.subscribers.add('ubuntu-main-sponsors') if component in ["universe", "multiverse"] and \ 'ubuntu-universe-sponsors' not in [str(s) for s in bug.subscribers]: bug.subscribers.add('ubuntu-universe-sponsors') if not component: bug.tags.append("needs-packaging") comment = Bug.NewComment(text=assemble_bug_comment_text(host, incoming, sourcepackage, version), subject="Fix in %s (%s)" % \ (sourcepackage, version)) bug.comments.add(comment) if bug.status != "Fix Committed": bug.status = "Fix Committed" bug.commit() def check_arguments(args): new_bug = False location = 'default' debuild_args = list() if len(sys.argv) == 2 and sys.argv[1] in ["--help", "-H"]: print USAGE sys.exit(0) if len(sys.argv) == 1: return (new_bug, location, debuild_args) if sys.argv[1] == "-n": new_bug = True if len(sys.argv)>2: if sys.argv[2].startswith("-"): debuild_args = sys.argv[2:] else: location = sys.argv[2] if len(sys.argv)>3: debuild_args = sys.argv[3:] else: if sys.argv[1].startswith("-"): debuild_args.append(sys.argv[1:]) else: location = sys.argv[1] if len(sys.argv)>2: debuild_args = sys.argv[2:] return (new_bug, location, debuild_args) def file_bug(sourcepackage, version): Bug = Connector.ConnectBug() Bug.authentication = os.path.expanduser("~/.lpcookie") try: bug = Bug.New(product={"name": sourcepackage, "target": "ubuntu"}, summary="Please sponsor %s %s" % \ (sourcepackage, version), description=\ "The new package will be uploaded to PPA shortly.") except: bug = Bug.New(product={"name": "ubuntu"}, summary="Please sponsor %s %s" % \ (sourcepackage, version), description=\ "The new package will be uploaded to PPA shortly.") print "Successfully filed bug %s: http://launchpad.net/bugs/%s" % \ (bug.bugnumber, bug.bugnumber) return bug.bugnumber def main(): (new_bug, location, debuild_args) = check_arguments(sys.argv) (sourcepackage, version) = get_name_and_version()[0] if new_bug: bugnumber = file_bug(sourcepackage, version) os.system("dch -a 'Fixes (LP: #%s)'" % bugnumber) if not call_debuild(debuild_args): sys.exit(1) changesfile = "../%s_%s_source.changes" % (sourcepackage, version) if not os.path.exists(os.path.expanduser(changesfile)): print >> sys.stderr, "%s does not exist." % \ os.path.expanduser(changesfile) sys.exit(1) host = lookup_dput_host(location) (dput_res, incoming) = call_dput(location, changesfile) if not dput_res: print >> sys.stderr, "%s was not uploaded." % changesfile sys.exit(1) fixed_lp_bugs = find_fixed_launchpad_bug(changesfile) if(fixed_lp_bugs): deal_with_bugreport(fixed_lp_bugs, host, incoming, sourcepackage, version) if __name__ == '__main__': main()