~launchpad-pqm/launchpad/devel

10637.3.1 by Guilherme Salgado
Use the default python version instead of a hard-coded version
1
#!/usr/bin/python -S
8687.15.22 by Karl Fogel
Add the copyright header block to the remaining .py files.
2
#
14027.3.4 by Jeroen Vermeulen
Automated import fixes and copyright updates.
3
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
8687.15.22 by Karl Fogel
Add the copyright header block to the remaining .py files.
4
# GNU Affero General Public License version 3 (see the file LICENSE).
5
5620.1.9 by Celso Providelo
applying review comments, r=bac.
6
# <james.troup@canonical.com>
7
# pylint: disable-msg=W0403
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
8
9
""" 'Sync' a source package by generating an upload.
10
11
This is a straight port of the original dak 'josie' tool to soyuz.
12
13
Long term once soyuz is monitoring other archives regularly, syncing
14
will become a matter of simply 'publishing' source from Debian unstable
15
wherever) into Ubuntu dapper and the whole fake upload trick can go away.
16
"""
13970.7.18 by William Grant
sync-source.py is a LaunchpadScript as well.
17
3024.3.5 by James Troup
Initial port of dak's josie
18
import errno
19
import os
20
import re
21
import shutil
22
import stat
23
import string
24
import tempfile
25
import urllib
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
26
14027.3.4 by Jeroen Vermeulen
Automated import fixes and copyright updates.
27
import _pythonpath
7675.916.98 by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes.
28
from _syncorigins import origins
29
import apt_pkg
30
from debian.deb822 import Dsc
7675.991.2 by Jeroen Vermeulen
Roll back lp:~launchpad/launchpad/recife.
31
from zope.component import getUtility
3024.3.5 by James Troup
Initial port of dak's josie
32
11516.3.1 by Jelmer Vernooij
Fix handling of unicode in sync source.
33
from canonical.database.sqlbase import (
34
    cursor,
35
    sqlvalues,
36
    )
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
37
from lp.archiveuploader.utils import (
38
    DpkgSourceError,
39
    extract_dpkg_source,
40
    )
11882.2.2 by Jonathan Lange
Clear up a heck of a lot of imports from canonical.launchpad.interfaces.
41
from lp.registry.interfaces.distribution import IDistributionSet
42
from lp.registry.interfaces.person import IPersonSet
9113.7.7 by Jonathan Lange
Update all the rest of the imports of PackagePublishingPocket.
43
from lp.registry.interfaces.pocket import PackagePublishingPocket
14606.2.5 by William Grant
Move the rest of canonical.librarian to lp.services.librarianserver.
44
from lp.services.librarian.client import LibrarianClient
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
45
from lp.services.scripts.base import (
46
    LaunchpadScript,
47
    LaunchpadScriptFailure,
48
    )
13785.8.3 by Julian Edwards
Make sync-source use the regexes from enums.py
49
from lp.soyuz.enums import (
50
    PackagePublishingStatus,
13785.8.6 by Julian Edwards
Move another regex into enums.py
51
    re_bug_numbers,
13785.8.3 by Julian Edwards
Make sync-source use the regexes from enums.py
52
    re_closes,
53
    re_lp_closes,
54
    )
11516.3.1 by Jelmer Vernooij
Fix handling of unicode in sync source.
55
from lp.soyuz.scripts.ftpmaster import (
56
    generate_changes,
57
    SyncSource,
58
    SyncSourceError,
59
    )
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
60
3024.3.5 by James Troup
Initial port of dak's josie
61
62
reject_message = ""
14075.1.8 by William Grant
Move dak_utils.re_no_epoch into sync-source.py, drop dak_utils.
63
re_no_epoch = re.compile(r"^\d+\:")
3024.3.5 by James Troup
Initial port of dak's josie
64
re_strip_revision = re.compile(r"-([^-]+)$")
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
65
re_changelog_header = re.compile(
66
    r"^\S+ \((?P<version>.*)\) .*;.*urgency=(?P<urgency>\w+).*")
3024.3.5 by James Troup
Initial port of dak's josie
67
68
69
Blacklisted = None
70
Library = None
71
Log = None
72
Options = None
73
74
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
75
def md5sum_file(filename):
76
    file_handle = open(filename)
77
    md5sum = apt_pkg.md5sum(file_handle)
78
    file_handle.close()
79
    return md5sum
3024.3.5 by James Troup
Initial port of dak's josie
80
81
11516.3.1 by Jelmer Vernooij
Fix handling of unicode in sync source.
82
def reject(str, prefix="Rejected: "):
3024.3.5 by James Troup
Initial port of dak's josie
83
    global reject_message
84
    if str:
85
        reject_message += prefix + str + "\n"
86
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
87
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
88
# Following two functions are borrowed and (modified) from apt-listchanges
89
def urgency_to_numeric(u):
90
    urgency_map = {
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
91
        'low': 1,
92
        'medium': 2,
93
        'high': 3,
94
        'emergency': 4,
95
        'critical': 4,
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
96
        }
97
    return urgency_map.get(u.lower(), 1)
98
99
100
def urgency_from_numeric(n):
101
    urgency_map = {
102
        1: 'low',
103
        2: 'medium',
104
        3: 'high',
105
        4: 'critical',
106
        }
107
    return urgency_map.get(n, 'low')
108
3024.3.5 by James Troup
Initial port of dak's josie
109
110
def parse_changelog(changelog_filename, previous_version):
111
    if not os.path.exists(changelog_filename):
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
112
        raise LaunchpadScriptFailure(
113
            "debian/changelog not found in extracted source.")
3024.3.5 by James Troup
Initial port of dak's josie
114
    urgency = urgency_to_numeric('low')
115
    changes = ""
116
    is_debian_changelog = 0
117
    changelog_file = open(changelog_filename)
118
    for line in changelog_file.readlines():
119
        match = re_changelog_header.match(line)
120
        if match:
5620.1.6 by Celso Providelo
Fixing bug 191230 (sync-source got broken in RF 5633) and add minimal tests to the mentioned script to avoid similar problems in the future.
121
            is_debian_changelog = 1
3024.3.5 by James Troup
Initial port of dak's josie
122
            if previous_version is None:
123
                previous_version = "9999:9999"
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
124
            elif apt_pkg.VersionCompare(
125
                match.group('version'), previous_version) > 0:
5620.1.9 by Celso Providelo
applying review comments, r=bac.
126
                urgency = max(
127
                    urgency_to_numeric(match.group('urgency')), urgency)
3024.3.5 by James Troup
Initial port of dak's josie
128
            else:
129
                break
130
        changes += line
131
132
    if not is_debian_changelog:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
133
        raise LaunchpadScriptFailure("header not found in debian/changelog")
3024.3.5 by James Troup
Initial port of dak's josie
134
135
    closes = []
136
    for match in re_closes.finditer(changes):
137
        bug_match = re_bug_numbers.findall(match.group(0))
138
        closes += map(int, bug_match)
139
140
    l = map(int, closes)
141
    l.sort()
142
    closes = map(str, l)
143
5620.1.1 by Celso Providelo
Fixing bug #189172 (parsing LP-bugs in incoming changeslog). Simply applying the given patch. No tests.
144
    lp_closes = []
145
    for match in re_lp_closes.finditer(changes):
146
        bug_match = re_bug_numbers.findall(match.group(0))
147
        lp_closes += map(int, bug_match)
148
149
    l = map(int, lp_closes)
150
    l.sort()
151
    lp_closes = map(str, l)
152
153
    return (changes, urgency_from_numeric(urgency), closes, lp_closes)
3024.3.5 by James Troup
Initial port of dak's josie
154
155
156
def fix_changelog(changelog):
3686.2.67 by Celso Providelo
applying review comments [r=thumper].
157
    """Fix debian/changelog entries to be in .changes compatible format."""
3024.3.5 by James Troup
Initial port of dak's josie
158
    fixed = []
159
    fixed_idx = -1
160
    for line in changelog.split("\n"):
161
        if line == "":
162
            fixed += [" ."]
163
            fixed_idx += 1
164
        elif line.startswith(" --"):
165
            # Strip any 'blank' lines preceeding the footer
166
            while fixed[fixed_idx] == " .":
167
                fixed.pop()
168
                fixed_idx -= 1
169
        else:
170
            fixed += [" %s" % (line)]
171
            fixed_idx += 1
172
    # Strip trailing 'blank' lines
173
    while fixed[fixed_idx] == " .":
174
        fixed.pop()
175
        fixed_idx -= 1
176
    fixed_changelog = "\n".join(fixed)
177
    fixed_changelog += "\n"
178
    return fixed_changelog
179
180
181
def parse_control(control_filename):
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
182
    """Parse a debian/control file.
3024.3.5 by James Troup
Initial port of dak's josie
183
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
184
    Extract section, priority and description if possible.
185
    """
3024.3.5 by James Troup
Initial port of dak's josie
186
    source_name = ""
187
    source_section = "-"
188
    source_priority = "-"
189
    source_description = ""
190
191
    if not os.path.exists(control_filename):
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
192
        raise LaunchpadScriptFailure(
193
            "debian/control not found in extracted source.")
3024.3.5 by James Troup
Initial port of dak's josie
194
    control_filehandle = open(control_filename)
195
    Control = apt_pkg.ParseTagFile(control_filehandle)
196
    while Control.Step():
197
        source = Control.Section.Find("Source")
198
        package = Control.Section.Find("Package")
199
        section = Control.Section.Find("Section")
200
        priority = Control.Section.Find("Priority")
201
        description = Control.Section.Find("Description")
10868.1.2 by Julian Edwards
some style tweaks in Colin's branch, before I land it.
202
        if source is not None:
203
            if section is not None:
10868.1.1 by Colin Watson
If Section or Priority is missing from the Source stanza of debian/control, leave it as "-" in the generated .changes file rather than setting it to "None".
204
                source_section = section
10868.1.2 by Julian Edwards
some style tweaks in Colin's branch, before I land it.
205
            if priority is not None:
10868.1.1 by Colin Watson
If Section or Priority is missing from the Source stanza of debian/control, leave it as "-" in the generated .changes file rather than setting it to "None".
206
                source_priority = priority
3024.3.5 by James Troup
Initial port of dak's josie
207
            source_name = source
10868.1.2 by Julian Edwards
some style tweaks in Colin's branch, before I land it.
208
        if package is not None and package == source_name:
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
209
            source_description = (
210
                "%-10s - %-.65s" % (package, description.split("\n")[0]))
3024.3.5 by James Troup
Initial port of dak's josie
211
    control_filehandle.close()
212
213
    return (source_section, source_priority, source_description)
214
215
216
def extract_source(dsc_filename):
217
    # Create and move into a temporary directory
11680.5.7 by Jelmer Vernooij
Simplify diff a bit, add missing chdir.
218
    tmpdir = tempfile.mkdtemp()
219
    old_cwd = os.getcwd()
3024.3.5 by James Troup
Initial port of dak's josie
220
221
    # Extract the source package
11680.5.3 by Jelmer Vernooij
Use extract_dpkg_source in ftp-master.
222
    try:
223
        extract_dpkg_source(dsc_filename, tmpdir)
224
    except DpkgSourceError, e:
225
        print " * command was '%s'" % (e.command)
226
        print e.output
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
227
        raise LaunchpadScriptFailure(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
228
            "'dpkg-source -x' failed for %s [return code: %s]." %
11680.5.3 by Jelmer Vernooij
Use extract_dpkg_source in ftp-master.
229
            (dsc_filename, e.result))
3024.3.5 by James Troup
Initial port of dak's josie
230
11680.5.7 by Jelmer Vernooij
Simplify diff a bit, add missing chdir.
231
    os.chdir(tmpdir)
232
    return (old_cwd, tmpdir)
3024.3.5 by James Troup
Initial port of dak's josie
233
234
235
def cleanup_source(tmpdir, old_cwd, dsc):
236
    # Sanity check that'll probably break if people set $TMPDIR, but
237
    # WTH, shutil.rmtree scares me
238
    if not tmpdir.startswith("/tmp/"):
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
239
        raise LaunchpadScriptFailure(
240
            "%s: tmpdir doesn't start with /tmp" % (tmpdir))
3024.3.5 by James Troup
Initial port of dak's josie
241
242
    # Move back and cleanup the temporary tree
243
    os.chdir(old_cwd)
244
    try:
245
        shutil.rmtree(tmpdir)
246
    except OSError, e:
247
        if errno.errorcode[e.errno] != 'EACCES':
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
248
            raise LaunchpadScriptFailure(
5620.1.9 by Celso Providelo
applying review comments, r=bac.
249
                "%s: couldn't remove tmp dir for source tree."
250
                % (dsc["source"]))
3024.3.5 by James Troup
Initial port of dak's josie
251
5620.1.9 by Celso Providelo
applying review comments, r=bac.
252
        reject("%s: source tree could not be cleanly removed."
253
               % (dsc["source"]))
3024.3.5 by James Troup
Initial port of dak's josie
254
        # We probably have u-r or u-w directories so chmod everything
255
        # and try again.
256
        cmd = "chmod -R u+rwx %s" % (tmpdir)
257
        result = os.system(cmd)
258
        if result != 0:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
259
            raise LaunchpadScriptFailure(
260
                "'%s' failed with result %s." % (cmd, result))
3024.3.5 by James Troup
Initial port of dak's josie
261
        shutil.rmtree(tmpdir)
262
    except:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
263
        raise LaunchpadScriptFailure(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
264
            "%s: couldn't remove tmp dir for source tree." % (dsc["source"]))
3024.3.5 by James Troup
Initial port of dak's josie
265
266
267
def check_dsc(dsc, current_sources, current_binaries):
268
    source = dsc["source"]
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
269
    if source in current_sources:
3024.3.5 by James Troup
Initial port of dak's josie
270
        source_component = current_sources[source][1]
271
    else:
272
        source_component = "universe"
273
    for binary in map(string.strip, dsc["binary"].split(',')):
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
274
        if binary in current_binaries:
3024.3.5 by James Troup
Initial port of dak's josie
275
            (current_version, current_component) = current_binaries[binary]
276
277
            # Check that a non-main source package is not trying to
278
            # override a main binary package
279
            if current_component == "main" and source_component != "main":
3024.3.43 by James Troup
Port -F/--force-more option.
280
                if not Options.forcemore:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
281
                    raise LaunchpadScriptFailure(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
282
                        "%s is in main but its source (%s) is not." %
283
                        (binary, source))
3024.3.43 by James Troup
Port -F/--force-more option.
284
                else:
14075.1.7 by William Grant
dak_utils.warn -> Log.warning
285
                    Log.warning(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
286
                        "%s is in main but its source (%s) is not - "
287
                        "continuing anyway." % (binary, source))
3024.3.5 by James Troup
Initial port of dak's josie
288
289
            # Check that a source package is not trying to override an
290
            # ubuntu-modified binary package
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
291
            ubuntu_bin = current_binaries[binary][0].find("ubuntu")
11680.5.6 by Jelmer Vernooij
Fix more lint issues.
292
            if not Options.force and ubuntu_bin != -1:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
293
                raise LaunchpadScriptFailure(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
294
                    "%s is trying to override %s_%s without -f/--force." %
295
                    (source, binary, current_version))
296
            print "I: %s [%s] -> %s_%s [%s]." % (
3686.2.67 by Celso Providelo
applying review comments [r=thumper].
297
                source, source_component, binary, current_version,
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
298
                current_component)
299
3024.3.5 by James Troup
Initial port of dak's josie
300
301
def import_dsc(dsc_filename, suite, previous_version, signing_rules,
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
302
               files_from_librarian, requested_by, origin, current_sources,
3024.3.5 by James Troup
Initial port of dak's josie
303
               current_binaries):
10245.4.17 by Jelmer Vernooij
Use debian_bundle.deb822.Dsc to parse Dsc files, as it also works with v3 files.
304
    dsc_file = open(dsc_filename, 'r')
305
    dsc = Dsc(dsc_file)
306
307
    if signing_rules.startswith("must be signed"):
308
        dsc_file.seek(0)
11516.4.1 by Jelmer Vernooij
Rely on newer version of python-debian that's now available.
309
        (gpg_pre, payload, gpg_post) = Dsc.split_gpg_and_payload(dsc_file)
10245.4.17 by Jelmer Vernooij
Use debian_bundle.deb822.Dsc to parse Dsc files, as it also works with v3 files.
310
        if gpg_pre == [] and gpg_post == []:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
311
            raise LaunchpadScriptFailure(
312
                "signature required for %s but not present" % dsc_filename)
10245.4.17 by Jelmer Vernooij
Use debian_bundle.deb822.Dsc to parse Dsc files, as it also works with v3 files.
313
        if signing_rules == "must be signed and valid":
314
            if (gpg_pre[0] != "-----BEGIN PGP SIGNED MESSAGE-----" or
315
                gpg_post[0] != "-----BEGIN PGP SIGNATURE-----"):
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
316
                raise LaunchpadScriptFailure(
317
                    "signature for %s invalid %r %r" %
318
                    (dsc_filename, gpg_pre, gpg_post))
10245.4.17 by Jelmer Vernooij
Use debian_bundle.deb822.Dsc to parse Dsc files, as it also works with v3 files.
319
320
    dsc_files = dict((entry['name'], entry) for entry in dsc['files'])
3024.3.5 by James Troup
Initial port of dak's josie
321
    check_dsc(dsc, current_sources, current_binaries)
322
323
    # Add the .dsc itself to dsc_files so it's listed in the Files: field
324
    dsc_base_filename = os.path.basename(dsc_filename)
325
    dsc_files.setdefault(dsc_base_filename, {})
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
326
    dsc_files[dsc_base_filename]["md5sum"] = md5sum_file(dsc_filename)
3024.3.5 by James Troup
Initial port of dak's josie
327
    dsc_files[dsc_base_filename]["size"] = os.stat(dsc_filename)[stat.ST_SIZE]
328
329
    (old_cwd, tmpdir) = extract_source(dsc_filename)
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
330
3024.3.5 by James Troup
Initial port of dak's josie
331
    # Get the upstream version
14075.1.8 by William Grant
Move dak_utils.re_no_epoch into sync-source.py, drop dak_utils.
332
    upstr_version = re_no_epoch.sub('', dsc["version"])
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
333
    if re_strip_revision.search(upstr_version):
334
        upstr_version = re_strip_revision.sub('', upstr_version)
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
335
3024.3.5 by James Troup
Initial port of dak's josie
336
    # Ensure the changelog file exists
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
337
    changelog_filename = (
338
        "%s-%s/debian/changelog" % (dsc["source"], upstr_version))
3024.3.5 by James Troup
Initial port of dak's josie
339
340
    # Parse it and then adapt it for .changes
5620.1.1 by Celso Providelo
Fixing bug #189172 (parsing LP-bugs in incoming changeslog). Simply applying the given patch. No tests.
341
    (changelog, urgency, closes, lp_closes) = parse_changelog(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
342
        changelog_filename, previous_version)
3024.3.5 by James Troup
Initial port of dak's josie
343
    changelog = fix_changelog(changelog)
344
345
    # Parse the control file
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
346
    control_filename = "%s-%s/debian/control" % (dsc["source"], upstr_version)
3024.3.5 by James Troup
Initial port of dak's josie
347
    (section, priority, description) = parse_control(control_filename)
348
349
    cleanup_source(tmpdir, old_cwd, dsc)
350
5620.1.9 by Celso Providelo
applying review comments, r=bac.
351
    changes = generate_changes(
352
        dsc, dsc_files, suite, changelog, urgency, closes, lp_closes,
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
353
        section, priority, description, files_from_librarian, requested_by,
5620.1.9 by Celso Providelo
applying review comments, r=bac.
354
        origin)
3024.3.5 by James Troup
Initial port of dak's josie
355
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
356
    output_filename = "%s_%s_source.changes" % (
14075.1.8 by William Grant
Move dak_utils.re_no_epoch into sync-source.py, drop dak_utils.
357
        dsc["source"], re_no_epoch.sub('', dsc["version"]))
3024.3.53 by James Troup
fix version number in generated .changes filename - thanks to Colin Watson.
358
3024.3.36 by James Troup
Produce an unsigned changes file
359
    filehandle = open(output_filename, 'w')
11516.3.1 by Jelmer Vernooij
Fix handling of unicode in sync source.
360
    try:
361
        changes.dump(filehandle, encoding="utf-8")
362
    finally:
363
        filehandle.close()
3024.3.5 by James Troup
Initial port of dak's josie
364
365
7548.1.1 by Celso Providelo
Fixing bug #238021 (sync-source.py not dealing with given component). This scripts isn't supported by LP, thus not tests.
366
def read_current_source(distro_series, valid_component=None, arguments=None):
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
367
    """Returns a dictionary of packages in 'suite'.
3024.3.5 by James Troup
Initial port of dak's josie
368
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
369
    The dictionary contains their version as the attribute.
370
    'component' is an optional list of (comma or whitespace separated)
371
    components to restrict the search to.
372
    """
3024.3.5 by James Troup
Initial port of dak's josie
373
    S = {}
374
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
375
    # XXX cprov 2007-07-10: This searches all pockets of the
376
    #     distro_series which is not what we want.
3024.3.37 by James Troup
Restrict read_current_source() to packages we're being asked to sync when possible. Document problems with lack of pocket restriction and inefficency of read_current_binaries().
377
    if Options.all:
3686.2.68 by Celso Providelo
more review comments [r=thumper].
378
        spp = distro_series.getSourcePackagePublishing(
5028.1.6 by David Murphy
Removed PackagePublishingPriority, PackagePublishingStatus, PackagePublishingPocket, PackageUploadStatus, & PackageUploadCustomFormat from canonical.lp.dbschema.
379
            status=PackagePublishingStatus.PUBLISHED,
11680.5.6 by Jelmer Vernooij
Fix more lint issues.
380
            pocket=PackagePublishingPocket.RELEASE)
3024.3.41 by James Troup
Fix s/except/else/ typo.
381
    else:
3024.3.37 by James Troup
Restrict read_current_source() to packages we're being asked to sync when possible. Document problems with lack of pocket restriction and inefficency of read_current_binaries().
382
        spp = []
383
        for package in arguments:
11436.1.4 by Michael Nelson
Fixed some test failures (use of len() now that its a result set, and two occurrences of the old name in ftpmaster-tools).
384
            spp.extend(distro_series.getPublishedSources(package))
3024.3.5 by James Troup
Initial port of dak's josie
385
386
    for sp in spp:
387
        component = sp.component.name
388
        version = sp.sourcepackagerelease.version
389
        pkg = sp.sourcepackagerelease.sourcepackagename.name
390
7548.1.1 by Celso Providelo
Fixing bug #238021 (sync-source.py not dealing with given component). This scripts isn't supported by LP, thus not tests.
391
        if (valid_component is not None and
392
            component != valid_component.name):
14075.1.7 by William Grant
dak_utils.warn -> Log.warning
393
            Log.warning(
7548.1.1 by Celso Providelo
Fixing bug #238021 (sync-source.py not dealing with given component). This scripts isn't supported by LP, thus not tests.
394
                "%s/%s: skipping because it is not in %s component" % (
395
                pkg, version, component))
3024.3.5 by James Troup
Initial port of dak's josie
396
            continue
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
397
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
398
        if pkg not in S:
3024.3.5 by James Troup
Initial port of dak's josie
399
            S[pkg] = [version, component]
400
        else:
401
            if apt_pkg.VersionCompare(S[pkg][0], version) < 0:
14075.1.7 by William Grant
dak_utils.warn -> Log.warning
402
                Log.warning(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
403
                    "%s: skipping because %s is < %s" % (
404
                    pkg, version, S[pkg][0]))
3024.3.5 by James Troup
Initial port of dak's josie
405
                S[pkg] = [version, component]
406
    return S
407
408
3686.2.68 by Celso Providelo
more review comments [r=thumper].
409
def read_current_binaries(distro_series):
410
    """Returns a dictionary of binaries packages in 'distro_series'.
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
411
412
    The dictionary contains their version and component as the attributes.
413
    """
3024.3.5 by James Troup
Initial port of dak's josie
414
    B = {}
415
5620.1.9 by Celso Providelo
applying review comments, r=bac.
416
    # XXX cprov 2007-07-10: This searches all pockets of the
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
417
    #     distro_series which is not what we want.
3024.3.37 by James Troup
Restrict read_current_source() to packages we're being asked to sync when possible. Document problems with lack of pocket restriction and inefficency of read_current_binaries().
418
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
419
    # XXX James Troup 2006-02-03: this is insanely slow due to how It
420
    #     SQLObject works. Can be limited, but only if we know what
421
    #     binaries we want to check against, which we don't know till
422
    #     we have the .dsc file and currently this function is
423
    #     run well before that.
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
424
    #
3686.2.68 by Celso Providelo
more review comments [r=thumper].
425
    #     for distroarchseries in distro_series.architectures:
3686.2.61 by Celso Providelo
sync-source.py s\distro*release\distro*series
426
    #         bpp = distroarchseries.getAllReleasesByStatus(
5028.1.6 by David Murphy
Removed PackagePublishingPriority, PackagePublishingStatus, PackagePublishingPocket, PackageUploadStatus, & PackageUploadCustomFormat from canonical.lp.dbschema.
427
    #             PackagePublishingStatus.PUBLISHED)
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
428
    #
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
429
    #         for bp in bpp:
430
    #             component = bp.component.name
431
    #             version = bp.binarypackagerelease.version
432
    #             pkg = bp.binarypackagerelease.binarypackagename.name
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
433
    #
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
434
    #             if pkg not in B:
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
435
    #                 B[pkg] = [version, component]
436
    #             else:
437
    #                 if apt_pkg.VersionCompare(B[pkg][0], version) < 0:
438
    #                     B[pkg] = [version, component]
439
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
440
    # XXX James Troup 2006-02-22: so... let's fall back on raw SQL
4785.4.4 by Celso Providelo
Fix #139550 (sync-source mistake using dbschemas)
441
    das_ids = [das.id for das in distro_series.architectures]
3500.4.15 by Celso Providelo
Fixing bug 141019 (sync-source.py queries are not restricted to ubuntu main_archives). Apply cowboy fixes to sync-source.py, code tested in drescher.
442
    archive_ids = [a.id for a in Options.todistro.all_distro_archives]
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
443
    cur = cursor()
444
    query = """
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
445
    SELECT bpn.name, bpr.version, c.name
446
    FROM binarypackagerelease bpr, binarypackagename bpn, component c,
7659.7.6 by Julian Edwards
Fix some sql syntax and one more reference to secure*
447
        binarypackagepublishinghistory sbpph, distroarchseries dar
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
448
    WHERE
449
        bpr.binarypackagename = bpn.id AND
450
             sbpph.binarypackagerelease = bpr.id AND
451
        sbpph.component = c.id AND
5121.2.7 by Stuart Bishop
More required code changes
452
        sbpph.distroarchseries = dar.id AND
4785.4.4 by Celso Providelo
Fix #139550 (sync-source mistake using dbschemas)
453
        sbpph.status = %s AND
3500.4.15 by Celso Providelo
Fixing bug 141019 (sync-source.py queries are not restricted to ubuntu main_archives). Apply cowboy fixes to sync-source.py, code tested in drescher.
454
        sbpph.archive IN %s AND
4785.4.4 by Celso Providelo
Fix #139550 (sync-source mistake using dbschemas)
455
        dar.id IN %s
3500.4.15 by Celso Providelo
Fixing bug 141019 (sync-source.py queries are not restricted to ubuntu main_archives). Apply cowboy fixes to sync-source.py, code tested in drescher.
456
     """ % sqlvalues(
3500.4.20 by Celso Providelo
merge from RF
457
        PackagePublishingStatus.PUBLISHED, archive_ids, das_ids)
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
458
    cur.execute(query)
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
459
3686.2.68 by Celso Providelo
more review comments [r=thumper].
460
    print "Getting binaries for %s..." % (distro_series.name)
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
461
    for (pkg, version, component) in cur.fetchall():
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
462
        if pkg not in B:
3024.3.42 by James Troup
Bypass SQLOBject and do a direct SQL query to get the performance back to something usable.
463
            B[pkg] = [version, component]
464
        else:
465
            if apt_pkg.VersionCompare(B[pkg][0], version) < 0:
3024.3.5 by James Troup
Initial port of dak's josie
466
                B[pkg] = [version, component]
467
    return B
468
469
470
def read_Sources(filename, origin):
471
    S = {}
472
473
    suite = origin["suite"]
474
    component = origin["component"]
475
    if suite:
476
        suite = "_%s" % (suite)
477
    if component:
478
        component = "_%s" % (component)
479
480
    filename = "%s%s%s_%s" % (origin["name"], suite, component, filename)
481
    sources_filehandle = open(filename)
482
    Sources = apt_pkg.ParseTagFile(sources_filehandle)
483
    while Sources.Step():
484
        pkg = Sources.Section.Find("Package")
485
        version = Sources.Section.Find("Version")
486
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
487
        if pkg in S and apt_pkg.VersionCompare(
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
488
            S[pkg]["version"], version) > 0:
3024.3.5 by James Troup
Initial port of dak's josie
489
            continue
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
490
3024.3.5 by James Troup
Initial port of dak's josie
491
        S[pkg] = {}
492
        S[pkg]["version"] = version
493
494
        directory = Sources.Section.Find("Directory", "")
495
        files = {}
496
        for line in Sources.Section.Find("Files").split('\n'):
497
            (md5sum, size, filename) = line.strip().split()
498
            files[filename] = {}
499
            files[filename]["md5sum"] = md5sum
500
            files[filename]["size"] = int(size)
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
501
            files[filename]["remote filename"] = (
502
                os.path.join(directory, filename))
3024.3.5 by James Troup
Initial port of dak's josie
503
        S[pkg]["files"] = files
504
    sources_filehandle.close()
505
    return S
506
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
507
508
def add_source(pkg, Sources, previous_version, suite, requested_by, origin,
509
               current_sources, current_binaries):
3024.3.5 by James Troup
Initial port of dak's josie
510
    print " * Trying to add %s..." % (pkg)
511
512
    # Check it's in the Sources file
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
513
    if pkg not in Sources:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
514
        raise LaunchpadScriptFailure(
515
            "%s doesn't exist in the Sources file." % (pkg))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
516
10245.4.10 by Jelmer Vernooij
Fix tests, use logger consistently everywhere.
517
    syncsource = SyncSource(Sources[pkg]["files"], origin, Log,
10245.4.4 by Jelmer Vernooij
Use SyncSource helper in sync-source.py.
518
        urllib.urlretrieve, Options.todistro)
519
    try:
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
520
        files_from_librarian = syncsource.fetchLibrarianFiles()
521
        dsc_filename = syncsource.fetchSyncFiles()
10245.4.6 by Jelmer Vernooij
Fix method name.
522
        syncsource.checkDownloadedFiles()
10245.4.4 by Jelmer Vernooij
Use SyncSource helper in sync-source.py.
523
    except SyncSourceError, e:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
524
        raise LaunchpadScriptFailure("Fetching files failed: %s" % (str(e),))
3024.3.5 by James Troup
Initial port of dak's josie
525
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
526
    if dsc_filename is None:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
527
        raise LaunchpadScriptFailure(
11680.5.6 by Jelmer Vernooij
Fix more lint issues.
528
            "No dsc filename in %r" % Sources[pkg]["files"].keys())
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
529
530
    import_dsc(os.path.abspath(dsc_filename), suite, previous_version,
10245.4.17 by Jelmer Vernooij
Use debian_bundle.deb822.Dsc to parse Dsc files, as it also works with v3 files.
531
               origin["dsc"], files_from_librarian, requested_by, origin,
10245.4.12 by Jelmer Vernooij
Support fetching multiple files from the librarian.
532
               current_sources, current_binaries)
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
533
3024.3.5 by James Troup
Initial port of dak's josie
534
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
535
class Percentages:
536
    """Helper to compute percentage ratios compared to a fixed total."""
537
538
    def __init__(self, total):
539
        self.total = total
540
541
    def get_ratio(self, number):
542
        """Report the ration of `number` to `self.total`, as a percentage."""
543
        return (float(number) / self.total) * 100
544
545
3024.3.5 by James Troup
Initial port of dak's josie
546
def do_diff(Sources, Suite, origin, arguments, current_binaries):
547
    stat_us = 0
548
    stat_cant_update = 0
549
    stat_updated = 0
550
    stat_uptodate_modified = 0
551
    stat_uptodate = 0
552
    stat_count = 0
553
    stat_broken = 0
554
    stat_blacklisted = 0
555
556
    if Options.all:
557
        packages = Suite.keys()
558
    else:
559
        packages = arguments
560
    packages.sort()
561
    for pkg in packages:
562
        stat_count += 1
10107.2.1 by James Westby
Handle syncing packages that aren't in Ubuntu which have versions < 0
563
        dest_version = Suite.get(pkg, [None, ""])[0]
3024.3.5 by James Troup
Initial port of dak's josie
564
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
565
        if pkg not in Sources:
3024.3.5 by James Troup
Initial port of dak's josie
566
            if not Options.all:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
567
                raise LaunchpadScriptFailure("%s: not found" % (pkg))
3024.3.5 by James Troup
Initial port of dak's josie
568
            else:
569
                print "[Ubuntu Specific] %s_%s" % (pkg, dest_version)
570
                stat_us += 1
571
                continue
572
11680.5.5 by Jelmer Vernooij
Review feedback from Gavin.
573
        if pkg in Blacklisted:
3024.3.5 by James Troup
Initial port of dak's josie
574
            print "[BLACKLISTED] %s_%s" % (pkg, dest_version)
575
            stat_blacklisted += 1
576
            continue
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
577
3024.3.5 by James Troup
Initial port of dak's josie
578
        source_version = Sources[pkg]["version"]
10107.2.1 by James Westby
Handle syncing packages that aren't in Ubuntu which have versions < 0
579
        if (dest_version is None
580
                or apt_pkg.VersionCompare(dest_version, source_version) < 0):
10107.2.3 by James Westby
Yay for tests.
581
            if (dest_version is not None
582
                    and (not Options.force
10107.2.1 by James Westby
Handle syncing packages that aren't in Ubuntu which have versions < 0
583
                        and dest_version.find("ubuntu") != -1)):
3024.3.5 by James Troup
Initial port of dak's josie
584
                stat_cant_update += 1
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
585
                print ("[NOT Updating - Modified] %s_%s (vs %s)"
586
                       % (pkg, dest_version, source_version))
3024.3.5 by James Troup
Initial port of dak's josie
587
            else:
588
                stat_updated += 1
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
589
                print ("[Updating] %s (%s [Ubuntu] < %s [%s])"
590
                       % (pkg, dest_version, source_version, origin["name"]))
3024.3.5 by James Troup
Initial port of dak's josie
591
                if Options.action:
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
592
                    add_source(
593
                        pkg, Sources,
594
                        Suite.get(pkg, ["0", ""])[0], Options.tosuite.name,
595
                        Options.requestor, origin, Suite, current_binaries)
3024.3.5 by James Troup
Initial port of dak's josie
596
        else:
597
            if dest_version.find("ubuntu") != -1:
5620.1.9 by Celso Providelo
applying review comments, r=bac.
598
                stat_uptodate_modified += 1
14149.2.1 by William Grant
Fix sync-source.py's "Nothing to update" logging to not crash. Regression in r13982.
599
                if Options.verbose or not Options.all:
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
600
                    print ("[Nothing to update (Modified)] %s_%s (vs %s)"
601
                           % (pkg, dest_version, source_version))
3024.3.5 by James Troup
Initial port of dak's josie
602
            else:
603
                stat_uptodate += 1
14149.2.1 by William Grant
Fix sync-source.py's "Nothing to update" logging to not crash. Regression in r13982.
604
                if Options.verbose or not Options.all:
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
605
                    print (
606
                        "[Nothing to update] %s (%s [ubuntu] >= %s [debian])"
607
                        % (pkg, dest_version, source_version))
3024.3.5 by James Troup
Initial port of dak's josie
608
609
    if Options.all:
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
610
        percentages = Percentages(stat_count)
3024.3.5 by James Troup
Initial port of dak's josie
611
        print
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
612
        print ("Out-of-date BUT modified: %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
613
            % (stat_cant_update, percentages.get_ratio(stat_cant_update)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
614
        print ("Updated:                  %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
615
            % (stat_updated, percentages.get_ratio(stat_updated)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
616
        print ("Ubuntu Specific:          %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
617
            % (stat_us, percentages.get_ratio(stat_us)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
618
        print ("Up-to-date [Modified]:    %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
619
            % (stat_uptodate_modified, percentages.get_ratio(
620
                stat_uptodate_modified)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
621
        print ("Up-to-date:               %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
622
               % (stat_uptodate, percentages.get_ratio(stat_uptodate)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
623
        print ("Blacklisted:              %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
624
               % (stat_blacklisted, percentages.get_ratio(stat_blacklisted)))
3686.2.63 by Celso Providelo
splitting sync-mirrors-list to another files and other style tweaks.
625
        print ("Broken:                   %3d (%.2f%%)"
14027.3.1 by Jeroen Vermeulen
Fix lots of lint in recently-changed files.
626
               % (stat_broken, percentages.get_ratio(stat_broken)))
3024.3.5 by James Troup
Initial port of dak's josie
627
        print "                          -----------"
628
        print "Total:                    %s" % (stat_count)
629
630
631
def objectize_options():
3691.274.2 by Celso Providelo
applying review comments, r=kiko
632
    """Parse given options.
3024.3.5 by James Troup
Initial port of dak's josie
633
3691.274.6 by Celso Providelo
more review comments
634
    Convert 'target_distro', 'target_suite' and 'target_component' to objects
3691.274.2 by Celso Providelo
applying review comments, r=kiko
635
    rather than strings.
636
    """
3691.312.71 by Celso Providelo
untested quick & dirty (tm) hack on ftpmaster-tools/sync-source.py.
637
    Options.todistro = getUtility(IDistributionSet)[Options.todistro]
3024.3.5 by James Troup
Initial port of dak's josie
638
3691.312.71 by Celso Providelo
untested quick & dirty (tm) hack on ftpmaster-tools/sync-source.py.
639
    if not Options.tosuite:
640
        Options.tosuite = Options.todistro.currentseries.name
641
    Options.tosuite = Options.todistro.getSeries(Options.tosuite)
3024.3.5 by James Troup
Initial port of dak's josie
642
3691.274.2 by Celso Providelo
applying review comments, r=kiko
643
    valid_components = (
3691.312.71 by Celso Providelo
untested quick & dirty (tm) hack on ftpmaster-tools/sync-source.py.
644
        dict([(component.name, component)
645
              for component in Options.tosuite.components]))
3691.312.73 by Celso Providelo
fixing Options.tocomponent in sync-source.py
646
647
    if Options.tocomponent is not None:
648
649
        if Options.tocomponent not in valid_components:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
650
            raise LaunchpadScriptFailure(
3691.312.73 by Celso Providelo
fixing Options.tocomponent in sync-source.py
651
                "%s is not a valid component for %s/%s."
652
                % (Options.tocomponent, Options.todistro.name,
653
                   Options.tosuite.name))
654
655
        Options.tocomponent = valid_components[Options.tocomponent]
3024.3.5 by James Troup
Initial port of dak's josie
656
3024.3.54 by James Troup
Use launchpad uids instead of an internal list. LP#38384
657
    # Fix up Options.requestor
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
658
    if not Options.requestor:
5620.1.9 by Celso Providelo
applying review comments, r=bac.
659
        Options.requestor = "katie"
3691.274.6 by Celso Providelo
more review comments
660
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
661
    PersonSet = getUtility(IPersonSet)
662
    person = PersonSet.getByName(Options.requestor)
663
    if not person:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
664
        raise LaunchpadScriptFailure(
665
            "Unknown LaunchPad user id '%s'." % (Options.requestor))
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
666
    Options.requestor = "%s <%s>" % (person.displayname,
5620.1.9 by Celso Providelo
applying review comments, r=bac.
667
                                     person.preferredemail.email)
3686.2.59 by Celso Providelo
raw diff on forked production sync-source.py
668
    Options.requestor = Options.requestor.encode("ascii", "replace")
3024.3.54 by James Troup
Use launchpad uids instead of an internal list. LP#38384
669
3024.3.5 by James Troup
Initial port of dak's josie
670
5620.1.7 by Celso Providelo
Extending tests for sync-source. Allowing not-found/empty blacklist and parsing generated changesfile.
671
def parseBlacklist(path):
672
    """Parse given file path as a 'blacklist'.
673
674
    Format:
675
676
    {{{
677
    # [comment]
678
    <sourcename> # [comment]
679
    }}}
680
681
    Return a blacklist dictionary where the keys are blacklisted source
682
    package names.
683
684
    Return an empty dictionary if the given 'path' doesn't exist.
685
    """
5620.1.9 by Celso Providelo
applying review comments, r=bac.
686
    blacklist = {}
5620.1.7 by Celso Providelo
Extending tests for sync-source. Allowing not-found/empty blacklist and parsing generated changesfile.
687
688
    try:
689
        blacklist_file = open(path)
690
    except IOError:
14075.1.7 by William Grant
dak_utils.warn -> Log.warning
691
        Log.warning('Could not find blacklist file on %s' % path)
5620.1.9 by Celso Providelo
applying review comments, r=bac.
692
        return blacklist
5620.1.7 by Celso Providelo
Extending tests for sync-source. Allowing not-found/empty blacklist and parsing generated changesfile.
693
694
    for line in blacklist_file:
695
        try:
696
            line = line[:line.index("#")]
697
        except ValueError:
698
            pass
699
        line = line.strip()
700
        if not line:
701
            continue
5620.1.9 by Celso Providelo
applying review comments, r=bac.
702
        blacklist[line] = ""
5620.1.7 by Celso Providelo
Extending tests for sync-source. Allowing not-found/empty blacklist and parsing generated changesfile.
703
    blacklist_file.close()
704
5620.1.9 by Celso Providelo
applying review comments, r=bac.
705
    return blacklist
5620.1.7 by Celso Providelo
Extending tests for sync-source. Allowing not-found/empty blacklist and parsing generated changesfile.
706
707
13970.7.18 by William Grant
sync-source.py is a LaunchpadScript as well.
708
class SyncSourceScript(LaunchpadScript):
709
710
    def add_my_options(self):
711
        self.parser.add_option("-a", "--all", dest="all",
712
                        default=False, action="store_true",
713
                        help="sync all packages")
714
        self.parser.add_option("-b", "--requested-by", dest="requestor",
715
                        help="who the sync was requested by")
716
        self.parser.add_option("-f", "--force", dest="force",
717
                        default=False, action="store_true",
718
                        help="force sync over the top of Ubuntu changes")
719
        self.parser.add_option("-F", "--force-more", dest="forcemore",
720
                        default=False, action="store_true",
721
                        help="force sync even when components don't match")
722
        self.parser.add_option("-n", "--noaction", dest="action",
723
                        default=True, action="store_false",
724
                        help="don't do anything")
725
726
        # Options controlling where to sync packages to:
727
        self.parser.add_option("-c", "--to-component", dest="tocomponent",
728
                        help="limit syncs to packages in COMPONENT")
729
        self.parser.add_option("-d", "--to-distro", dest="todistro",
730
                        default='ubuntu', help="sync to DISTRO")
731
        self.parser.add_option("-s", "--to-suite", dest="tosuite",
732
                        help="sync to SUITE (aka distroseries)")
733
734
        # Options controlling where to sync packages from:
735
        self.parser.add_option("-C", "--from-component", dest="fromcomponent",
736
                        help="sync from COMPONENT")
737
        self.parser.add_option("-D", "--from-distro", dest="fromdistro",
738
                        default='debian', help="sync from DISTRO")
739
        self.parser.add_option("-S", "--from-suite", dest="fromsuite",
740
                        help="sync from SUITE (aka distroseries)")
741
        self.parser.add_option("-B", "--blacklist", dest="blacklist_path",
742
                        default="/srv/launchpad.net/dak/sync-blacklist.txt",
743
                        help="Blacklist file path.")
744
745
    def main(self):
746
        global Blacklisted, Library, Log, Options
747
748
        Log = self.logger
749
        Options = self.options
750
751
        distro = Options.fromdistro.lower()
752
        if not Options.fromcomponent:
753
            Options.fromcomponent = origins[distro]["default component"]
754
        if not Options.fromsuite:
755
            Options.fromsuite = origins[distro]["default suite"]
756
757
        # Sanity checks on options
758
        if not Options.all and not self.args:
14075.1.6 by William Grant
Use LaunchpadScriptFailure instead of dak_utils.fubar.
759
            raise LaunchpadScriptFailure(
13970.7.18 by William Grant
sync-source.py is a LaunchpadScript as well.
760
                "Need -a/--all or at least one package name as an argument.")
761
762
        apt_pkg.init()
763
        Library = LibrarianClient()
764
765
        objectize_options()
766
767
        Blacklisted = parseBlacklist(Options.blacklist_path)
768
769
        origin = origins[Options.fromdistro]
770
        origin["suite"] = Options.fromsuite
771
        origin["component"] = Options.fromcomponent
772
773
        Sources = read_Sources("Sources", origin)
774
        Suite = read_current_source(
775
            Options.tosuite, Options.tocomponent, self.args)
776
        current_binaries = read_current_binaries(Options.tosuite)
777
        do_diff(Sources, Suite, origin, self.args, current_binaries)
3024.3.5 by James Troup
Initial port of dak's josie
778
779
780
if __name__ == '__main__':
13970.7.18 by William Grant
sync-source.py is a LaunchpadScript as well.
781
    SyncSourceScript('sync-source', 'ro').lock_and_run()