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