Merge lp:~james-w/ubuntu-archive-tools/improved-sync-helper into lp:ubuntu-archive-tools

Proposed by James Westby on 2010-01-04
Status: Merged
Approved by: Steve Kowalik on 2010-01-05
Approved revision: not available
Merge reported by: Steve Kowalik
Merged at revision: not available
Proposed branch: lp:~james-w/ubuntu-archive-tools/improved-sync-helper
Merge into: lp:ubuntu-archive-tools
Diff against target: 221 lines (+160/-31)
1 file modified
sync-helper.py (+160/-31)
To merge this branch: bzr merge lp:~james-w/ubuntu-archive-tools/improved-sync-helper
Reviewer Review Type Date Requested Status
Steve Kowalik (community) 2010-01-04 Approve on 2010-01-05
Review via email: mp+16779@code.launchpad.net
To post a comment you must log in.
James Westby (james-w) wrote :

Hi Steven,

Please review my changes to sync-helper.py and see if you like
them. I didn't want to unilaterally make them to your script,
but I think these improvements make it a lot more usable.

Thanks for writing the initial version. Processing syncs is much
quicker with this script now.

Thanks,

James

91. By James Westby on 2010-01-04

Allow changing suite back to unstable.

92. By James Westby on 2010-01-04

Mark commenters that can upload the package with (*).

This makes it easier to see if sponsorship is still needed.

93. By James Westby on 2010-01-04

Get all the info up-front to speed up processing.

94. By James Westby on 2010-01-04

Add progress output.

Also avoid another call to rmadison by re-using the info that we have.

95. By James Westby on 2010-01-04

Fix a thinko that caused crashes when looking up the component

96. By James Westby on 2010-01-04

Also consider package sets when looking for uploaders.

Steve Kowalik (stevenk) wrote :

Hi James,

This all looks totally awesome! Thanks for the great changes, I'll merge them into trunk soonish.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'sync-helper.py'
2--- sync-helper.py 2009-11-20 20:29:12 +0000
3+++ sync-helper.py 2010-01-04 19:09:12 +0000
4@@ -3,22 +3,108 @@
5 # Copyright 2009 Canonical Ltd.
6
7 import os, sys
8-from launchpadlib.launchpad import Launchpad, STAGING_SERVICE_ROOT
9+import subprocess
10+from launchpadlib.launchpad import Launchpad, EDGE_SERVICE_ROOT, STAGING_SERVICE_ROOT
11+import webbrowser
12
13 APP_NAME = 'sync-helper'
14 CACHE_DIR = os.path.expanduser('~/.launchpadlib/cache')
15-SERVICE_ROOT = STAGING_SERVICE_ROOT
16+SERVICE_ROOT = EDGE_SERVICE_ROOT
17+
18+
19+class Bug(object):
20+
21+ def __init__(self, number):
22+ self.number = number
23+ self.title = None
24+ self.package = None
25+ self.reporter = None
26+ self.content = None
27+
28
29 def length(collection):
30 # XXX: Workaround bug 274074. Thanks wgrant.
31 return int(collection._wadl_resource.representation['total_size'])
32
33-def prompt(text):
34- print "%s [Show/sKip/sYnc] " % text
35- return sys.stdin.readline().rstrip()
36-
37-def sync(bug, syncfile):
38- syncfile.write("sync %s -f\n" % bug)
39+def rmadison(distro, package):
40+ proc = subprocess.Popen(["/usr/bin/rmadison", "-u", distro, package],
41+ stdout=subprocess.PIPE)
42+ (output, _) = proc.communicate()
43+ return output.splitlines()
44+
45+def get_components(package, debian_details):
46+ components = {}
47+ for line in debian_details.splitlines():
48+ if line.strip() == "":
49+ continue
50+ series_component = line.split("|")[2].strip()
51+ archs = line.split("|")[3].strip().split(", ")
52+ if "source" in archs:
53+ if "/" in series_component:
54+ series, component = series_component.split("/")
55+ components[series] = component
56+ else:
57+ components[series_component] = "main"
58+ return components
59+
60+def ubuntu_details(package, current_series):
61+ output = rmadison("ubuntu", package)
62+ new_output = []
63+ for line in output:
64+ parts = line.split("|")
65+ if current_series in parts[2]:
66+ new_output.append(line)
67+ return new_output
68+
69+def debian_details(package):
70+ return rmadison("debian", package)
71+
72+def canUpload(distribution, person, package_name):
73+ if distribution.main_archive.isSourceUploadAllowed(
74+ distroseries=distribution.current_series, person=person,
75+ sourcepackagename=package_name):
76+ return True
77+ pubs = distribution.main_archive.getPublishedSources(
78+ distro_series=distribution.current_series, exact_match=True,
79+ pocket="Release", status="Published", source_name=package_name)
80+ pubs = [pub for pub in pubs]
81+ if len(pubs) < 1:
82+ return False
83+ component = pubs[0].component_name
84+ for perm in distribution.main_archive.getPermissionsForPerson(person=person):
85+ if perm.permission != 'Archive Upload Rights':
86+ continue
87+ if perm.component_name == component:
88+ return True
89+ if perm.source_package_name == package_name:
90+ return True
91+ return False
92+
93+def prompt(bug, suite, full=True):
94+ sys.stdout.write("%s: %s\n" % (bug.number, bug.title))
95+ if full:
96+ sys.stdout.write(bug.ubuntu_details + "\n")
97+ sys.stdout.write(bug.debian_details + "\n")
98+ msg = "[Show/sKip/sYnc from %s/" % (suite,)
99+ if suite == "unstable" or suite == "experimental":
100+ msg += "switch to Testing/"
101+ elif suite == "testing":
102+ msg += "switch to Unstable/"
103+ if suite == "testing" or suite == "unstable":
104+ msg += "switch to Experimental/"
105+ elif suite == "experimental":
106+ msg += "switch to Unstable/"
107+ msg += "Open bug]: "
108+ sys.stdout.write(msg)
109+ sys.stdout.flush()
110+ return sys.stdin.readline().rstrip().upper()
111+
112+def sync(bug, syncfile, suite="unstable", component="main"):
113+ params = {"bug": bug.number,
114+ "suite": suite,
115+ "component": component,
116+ }
117+ syncfile.write("sync %(bug)s -f -S %(suite)s -C %(component)s\n" % params)
118
119 def main(args):
120 f = None
121@@ -27,35 +113,78 @@
122 except:
123 print "%s: Require a filename to write to!" % args[0]
124 sys.exit(1)
125- print "Connecting to LP ... "
126+ sys.stdout.write("Connecting to LP ... ")
127+ sys.stdout.flush()
128 launchpad = Launchpad.login_with(APP_NAME, SERVICE_ROOT, CACHE_DIR)
129 pillar = launchpad.projects['ubuntu']
130 subscriber = launchpad.people['ubuntu-archive']
131- print "Done"
132- print "Loading bugs ... "
133- bugs = pillar.searchTasks(bug_subscriber = subscriber, search_text = 'sync')
134- bugs_cache = {}
135- bug_numbers = {}
136+ ubuntu_series = pillar.current_series.name
137+ sys.stdout.write("Done\n")
138+ sys.stdout.write("Loading bugs (this may take some time, go get a "
139+ "cup of tea) ... \n")
140+ sync_bugs = []
141+ bugs = pillar.searchTasks(bug_subscriber=subscriber, search_text='qcad')
142+ num_bugs = length(bugs)
143+ bugs_processed = 0
144+ prev_line = ""
145 for bugtask in bugs:
146- bugs_cache[bugtask.bug.title] = bugtask.bug.description
147- for i in reversed(bugtask.bug.messages_collection):
148- bugs_cache[bugtask.bug.title] += i.content
149- bug_numbers[bugtask.bug.title] = bugtask.bug.id
150- print "Done"
151+ bugs_processed += 1
152+ sys.stdout.write("\r" + " "*len(prev_line) + "\r")
153+ prev_line = "%d/%d" % (bugs_processed, num_bugs)
154+ sys.stdout.write(prev_line)
155+ sys.stdout.flush()
156+ if " (Ubuntu)" not in bugtask.bug_target_name:
157+ continue
158+ bug = Bug(bugtask.bug.id)
159+ bug.title = bugtask.bug.title
160+ bug.package = bugtask.bug_target_name.rsplit(" ", 1)[0]
161+ next_line_part = ": %s" % (bug.package,)
162+ sys.stdout.write(next_line_part)
163+ prev_line += next_line_part
164+ sys.stdout.flush()
165+ bug.content = bugtask.bug.description
166+ bug.reporter = bugtask.bug.owner
167+ for i in reversed(bugtask.bug.messages):
168+ bug.content += "\n=============================================\n"
169+ star = ""
170+ if canUpload(pillar, i.owner, bug.package):
171+ star = "(*)"
172+ bug.content += "%s%s said %s on %s:\n\n" % (i.owner.name, star,
173+ i.subject, str(i.date_created))
174+ bug.content += i.content
175+ bug.ubuntu_details = "\n".join(ubuntu_details(bug.package, ubuntu_series))
176+ bug.debian_details = "\n".join(debian_details(bug.package))
177+ bug.components = get_components(bug.package, bug.debian_details)
178+ sync_bugs.append(bug)
179+ sys.stdout.write("\r" + " "*len(prev_line) + "\r")
180+ sys.stdout.write("Done, %d packages to consider.\n" % (len(sync_bugs),))
181
182- for title in bugs_cache.keys():
183- ret = prompt(title)
184- if ret == 'S':
185- print bugs_cache[title]
186- ret = prompt(title)
187- if ret == 'Y':
188- sync(bug_numbers[title], f)
189+ for bug in sync_bugs:
190+ sys.stdout.write("\n==========================\n")
191+ finished = False
192+ suite = "unstable"
193+ component = "main"
194+ if suite in bug.components:
195+ component = bug.components[suite]
196+ full = True
197+ while not finished:
198+ ret = prompt(bug, suite, full=full)
199+ if ret == 'S':
200+ print bug.content
201 elif ret == 'K':
202- continue
203- elif ret == 'K':
204- continue
205- elif ret == 'Y':
206- sync(bug_numbers[title], f)
207+ finished = True
208+ elif ret == 'Y':
209+ sync(bug, f, suite=suite, component=component)
210+ finished = True
211+ elif ret == 'T':
212+ suite = "testing"
213+ elif ret == 'U':
214+ suite = "unstable"
215+ elif ret == 'E':
216+ suite = "experimental"
217+ elif ret == 'O':
218+ webbrowser.open("https://bugs.launchpad.net/bugs/%s" % bug.number)
219+ full = False
220 f.close()
221 return 0
222

Subscribers

People subscribed via source and target branches