~brz/brz-debian/byoci

126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
1
#    import_dsc.py -- Import a series of .dsc files.
2
#    Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
260 by James Westby
Copyright updates
3
#              (C) 2008 Canonical Ltd.
148 by James Westby
Fix up some copyright notices.
4
#
5
#    Code is also taken from bzrtools, which is
6
#             (C) 2005, 2006, 2007 Aaron Bentley <aaron.bentley@utoronto.ca>
7
#             (C) 2005, 2006 Canonical Limited.
8
#             (C) 2006 Michael Ellerman.
9
#    and distributed under the GPL, version 2 or later.
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
10
#    
11
#    This file is part of bzr-builddeb.
12
#
13
#    bzr-builddeb is free software; you can redistribute it and/or modify
14
#    it under the terms of the GNU General Public License as published by
15
#    the Free Software Foundation; either version 2 of the License, or
16
#    (at your option) any later version.
17
#
18
#    bzr-builddeb is distributed in the hope that it will be useful,
19
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
20
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
#    GNU General Public License for more details.
22
#
23
#    You should have received a copy of the GNU General Public License
24
#    along with bzr-builddeb; if not, write to the Free Software
25
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
26
#
27
750 by Jelmer Vernooij
use relative imports.
28
from __future__ import absolute_import
494.3.8 by Jelmer Vernooij
Move more functionality onto UpstreamSource classes.
29
747 by Andrew Starr-Bochicchio
import_dsc.py: Use calendar.timegm instead of time.mktime when importing
30
import calendar
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
31
import os
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
32
import shutil
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
33
import stat
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
34
import subprocess
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
35
import tempfile
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
36
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
37
from debian import deb822
38
from debian.changelog import Version, Changelog, VersionError
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
39
750 by Jelmer Vernooij
use relative imports.
40
from ... import (
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
41
    controldir,
750 by Jelmer Vernooij
use relative imports.
42
    osutils,
43
    )
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
44
from ...export import (
45
    export,
46
    )
750 by Jelmer Vernooij
use relative imports.
47
from ...config import ConfigObj
48
from ...errors import (
49
    AlreadyBranchError,
50
    BzrCommandError,
51
    NotBranchError,
52
    NoWorkingTree,
53
    UnrelatedBranches,
54
    )
55
from ...revision import NULL_REVISION
56
from ...trace import warning, mutter
57
from ...transport import (
370.3.4 by Muharem Hrnjadovic
Revised the code to use the do_catching_redirections() utility from bzrlib and removed repetitive code.
58
    get_transport,
59
    )
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
60
750 by Jelmer Vernooij
use relative imports.
61
from .bzrtools_import import import_dir
62
from .errors import (
613.5.7 by Jelmer Vernooij
Support extracting pristine tarball versions with multiple upstream revisions.
63
    MultipleUpstreamTarballsNotSupported,
578.2.8 by Jelmer Vernooij
Avoid unnecessary has_version call.
64
    PackageVersionNotPresent,
494.3.8 by Jelmer Vernooij
Move more functionality onto UpstreamSource classes.
65
    UpstreamAlreadyImported,
66
    UpstreamBranchAlreadyMerged,
67
    )
750 by Jelmer Vernooij
use relative imports.
68
from .util import (
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
69
    FORMAT_1_0,
506.1.5 by Jelmer Vernooij
Add constant for format strings.
70
    FORMAT_3_0_QUILT,
71
    FORMAT_3_0_NATIVE,
570.2.17 by Jelmer Vernooij
Pass along component with tarballs.
72
    component_from_orig_tarball,
570.2.7 by Jelmer Vernooij
Factor out extracting of orig tarballs.
73
    extract_orig_tarballs,
377 by James Westby
Handle redirects in more cases. Thanks Muharem.
74
    get_commit_info_from_changelog,
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
75
    md5sum_filename,
377 by James Westby
Handle redirects in more cases. Thanks Muharem.
76
    open_file_via_transport,
77
    open_transport,
423.2.1 by John Arbash Meinel
Fix bug #508251, fall back to iso-8859-1 for author info if utf-8 fails.
78
    safe_decode,
387 by James Westby
Handle no-trees repo in merge-upstream, and subprocess_setup in more places.
79
    subprocess_setup,
375.2.2 by Muharem Hrnjadovic
Changes:
80
    )
750 by Jelmer Vernooij
use relative imports.
81
from .upstream.pristinetar import (
561.1.1 by Jelmer Vernooij
Move pristine tar upstream to upstream/pristinetar.
82
    PristineTarSource,
83
    )
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
84
85
130 by James Westby
Improve the handling of strange .dsc files.
86
class DscCache(object):
87
562.1.1 by Max Bowsher
Mend inconsistencies where different indent widths are used at different points
88
    def __init__(self, transport=None):
89
        self.cache = {}
90
        self.transport_cache = {}
91
        self.transport = transport
92
93
    def get_dsc(self, name):
94
95
        if name in self.cache:
96
            dsc1 = self.cache[name]
97
        else:
98
            # Obtain the dsc file, following any redirects as needed.
99
            filename, transport = open_transport(name)
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
100
            with open_file_via_transport(filename, transport) as f1:
562.1.1 by Max Bowsher
Mend inconsistencies where different indent widths are used at different points
101
                dsc1 = deb822.Dsc(f1)
102
            self.cache[name] = dsc1
103
            self.transport_cache[name] = transport
104
105
        return dsc1
106
107
    def get_transport(self, name):
108
        return self.transport_cache[name]
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
109
643.1.2 by Jelmer Vernooij
Some refactoring.
110
130 by James Westby
Improve the handling of strange .dsc files.
111
class DscComp(object):
112
562.1.1 by Max Bowsher
Mend inconsistencies where different indent widths are used at different points
113
    def __init__(self, cache):
114
        self.cache = cache
130 by James Westby
Improve the handling of strange .dsc files.
115
562.1.1 by Max Bowsher
Mend inconsistencies where different indent widths are used at different points
116
    def cmp(self, dscname1, dscname2):
117
        dsc1 = self.cache.get_dsc(dscname1)
118
        dsc2 = self.cache.get_dsc(dscname2)
119
        v1 = Version(dsc1['Version'])
120
        v2 = Version(dsc2['Version'])
121
        if v1 == v2:
122
            return 0
123
        if v1 > v2:
124
            return 1
125
        return -1
129 by James Westby
Support importing the second set of .dsc.
126
127
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
128
class DistributionBranchSet(object):
129
    """A collection of DistributionBranches with an ordering.
130
131
    A DistributionBranchSet collects a group of DistributionBranches
132
    and an order, and then can provide the branches with information
133
    about their place in the relationship with other branches.
134
    """
135
136
    def __init__(self):
137
        """Create a DistributionBranchSet."""
138
        self._branch_list = []
139
140
    def add_branch(self, branch):
141
        """Adds a DistributionBranch to the end of the list.
142
143
        Appends the passed distribution branch to the end of the list
144
        that this DistributionBranchSet represents. It also provides
145
        the distribution branch with a way to get the branches that
146
        are before and after it in the list.
147
148
        It will call branch.set_get_lesser_branches_callback() and
149
        branch.set_get_greater_branches_callback(), passing it methods
150
        that the DistributionBranch can call to get the list of branches
151
        before it in the list and after it in the list respectively.
152
        The passed methods take no arguments and return a list (possibly
153
        empty) of the desired branches.
154
155
        :param branch: the DistributionBranch to add.
156
        """
157
        self._branch_list.append(branch)
158
        lesser_callback = self._make_lesser_callback(branch)
159
        branch.set_get_lesser_branches_callback(lesser_callback)
160
        greater_callback = self._make_greater_callback(branch)
161
        branch.set_get_greater_branches_callback(greater_callback)
162
163
    def _make_lesser_callback(self, branch):
164
        return lambda: self.get_lesser_branches(branch)
165
166
    def _make_greater_callback(self, branch):
167
        return lambda: self.get_greater_branches(branch)
168
169
    def get_lesser_branches(self, branch):
170
        """Return the list of branches less than the argument.
171
172
        :param branch: The branch that all branches returned must be less
173
            than.
174
        :return: a (possibly empty) list of all the branches that are
175
            less than the argument. The list is sorted starting with the
176
            least element.
177
        """
178
        index = self._branch_list.index(branch)
179
        return self._branch_list[:index]
180
181
    def get_greater_branches(self, branch):
182
        """Return the list of branches greater than the argument.
183
184
        :param branch: The branch that all branches returned must be greater
185
            than.
186
        :return: a (possibly empty) list of all the branches that are
187
            greater than the argument. The list is sorted starting with the
188
            least element.
189
        """
190
        index = self._branch_list.index(branch)
191
        return self._branch_list[index+1:]
192
193
643.1.2 by Jelmer Vernooij
Some refactoring.
194
def checkout_upstream_version(tree, package, version, revisions):
195
    """Checkout an upstream version from the pristine tar source.
196
197
    """
198
    tree.update(revision=revisions[None])
199
    parent_ids = []
200
    for component in sorted(revisions.keys()):
201
        revid = revisions[component]
202
        if component is not None:
203
            component_tree = tree.branch.repository.revision_tree(revid)
204
            export(component_tree, os.path.join(tree.basedir, component), format='dir')
205
        parent_ids.append(revid)
206
    tree.set_parent_ids(parent_ids)
207
208
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
209
class DistributionBranch(object):
210
    """A DistributionBranch is a representation of one line of development.
211
212
    It is a branch that is linked to a line of development, such as Debian
213
    unstable. It also has associated branches, some of which are "lesser"
214
    and some are "greater". A lesser branch is one that this branch
215
    derives from. A greater branch is one that derives from this. For
216
    instance Debian experimental would have unstable as a lesser branch,
217
    and vice-versa. It is assumed that a group of DistributionBranches will
218
    have a total ordering with respect to these relationships.
219
    """
220
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
221
    def __init__(self, branch, pristine_upstream_branch, tree=None,
638 by Vincent Ladeuil
Fix the returned values when dpkg-mergechangelogs is not available.
222
                 pristine_upstream_tree=None):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
223
        """Create a distribution branch.
224
243 by James Westby
Initial support for transitioning from native to non-native and back.
225
        You can only import packages on to the DistributionBranch
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
226
        if both tree and pristine_upstream_tree are provided.
243 by James Westby
Initial support for transitioning from native to non-native and back.
227
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
228
        :param branch: the Branch for the packaging part.
638 by Vincent Ladeuil
Fix the returned values when dpkg-mergechangelogs is not available.
229
        :param pristine_upstream_branch: the Branch for the pristine tar part,
230
            if any.
243 by James Westby
Initial support for transitioning from native to non-native and back.
231
        :param tree: an optional tree for the branch.
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
232
        :param pristine_upstream_tree: an optional tree for the
638 by Vincent Ladeuil
Fix the returned values when dpkg-mergechangelogs is not available.
233
            pristine_upstream_branch.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
234
        """
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
235
        self.branch = branch
494.3.7 by Jelmer Vernooij
Move upstream_tag_name to PristineTarSource.
236
        self.tree = tree
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
237
        self.pristine_upstream_branch = pristine_upstream_branch
238
        self.pristine_upstream_tree = pristine_upstream_tree
239
        if pristine_upstream_branch is not None:
240
            self.pristine_upstream_source = PristineTarSource(
241
                branch=pristine_upstream_branch, tree=pristine_upstream_tree)
494.3.7 by Jelmer Vernooij
Move upstream_tag_name to PristineTarSource.
242
        else:
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
243
            self.pristine_upstream_source = None
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
244
        self.get_lesser_branches = None
245
        self.get_greater_branches = None
246
247
    def set_get_lesser_branches_callback(self, callback):
248
        """Set the callback to get the branches "lesser" than this.
249
250
        The function passed to this method will be used to get the
251
        list of branches that are "lesser" than this one. It is
252
        expected to require no arguments, and to return the desired
253
        (possibly empty) list of branches. The returned list should
254
        be sorted starting with the least element.
255
256
        :param callback: a function that is called to get the desired list
257
            of branches.
258
        """
259
        self.get_lesser_branches = callback
260
261
    def set_get_greater_branches_callback(self, callback):
262
        """Set the callback to get the branches "greater" than this.
263
264
        The function passed to this method will be used to get the
265
        list of branches that are "greater" than this one. It is
266
        expected to require no arguments, and to return the desired
267
        (possibly empty) list of branches. The returned list should
268
        be sorted starting with the least element.
269
270
        :param callback: a function that is called to get the desired list
271
            of branches.
272
        """
273
        self.get_greater_branches = callback
274
229 by James Westby
Use file ids from other trees.
275
    def get_other_branches(self):
276
        """Return all the other branches in this set.
277
278
        The returned list will be ordered, and will not contain this
279
        branch.
280
281
        :return: a list of all the other branches in this set (if any).
282
        """
283
        return self.get_lesser_branches() + self.get_greater_branches()
284
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
285
    def tag_name(self, version):
286
        """Gets the name of the tag that is used for the version.
287
288
        :param version: the Version object that the tag should refer to.
289
        :return: a String with the name of the tag.
290
        """
316 by James Westby
Don't use the distribution name in the tags, fixing myriad issues.
291
        return str(version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
292
293
    def _has_version(self, branch, tag_name, md5=None):
578.2.15 by Jelmer Vernooij
Simplify has_version.
294
        if not branch.tags.has_tag(tag_name):
295
            return False
296
        revid = branch.tags.lookup_tag(tag_name)
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
297
        with branch.lock_read():
578.2.15 by Jelmer Vernooij
Simplify has_version.
298
            graph = branch.repository.get_graph()
299
            if not graph.is_ancestor(revid, branch.last_revision()):
300
                return False
301
        if md5 is None:
302
            return True
303
        rev = branch.repository.get_revision(revid)
304
        try:
305
            return rev.properties['deb-md5'] == md5
306
        except KeyError:
307
            warning("tag %s present in branch, but there is no "
308
                "associated 'deb-md5' property" % tag_name)
309
            return False
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
310
311
    def has_version(self, version, md5=None):
312
        """Whether this branch contains the package version specified.
313
314
        The version must be judged present by having the appropriate tag
315
        in the branch. If the md5 argument is not None then the string
316
        passed must the the md5sum that is associated with the revision
317
        pointed to by the tag.
318
319
        :param version: a Version object to look for in this branch.
320
        :param md5: a string with the md5sum that if not None must be
321
            associated with the revision.
322
        :return: True if this branch contains the specified version of the
323
            package. False otherwise.
324
        """
325
        tag_name = self.tag_name(version)
327.1.23 by James Westby
Fallback to old tag names when looking for the upstream branch.
326
        if self._has_version(self.branch, tag_name, md5=md5):
327
            return True
328
        debian_tag_name = "debian-" + tag_name
329
        if self._has_version(self.branch, debian_tag_name, md5=md5):
330
            return True
331
        ubuntu_tag_name = "ubuntu-" + tag_name
332
        if self._has_version(self.branch, ubuntu_tag_name, md5=md5):
333
            return True
334
        return False
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
335
336
    def contained_versions(self, versions):
337
        """Splits a list of versions depending on presence in the branch.
338
339
        Partitions the input list of versions depending on whether they
340
        are present in the branch or not.
341
342
        The two output lists will be sorted in the same order as the input
343
        list.
344
345
        :param versions: a list of Version objects to look for in the
346
            branch. May be an empty list.
347
        :return: A tuple of two lists. The first list is the list of those
348
            items from the input list that are present in the branch. The
349
            second list is the list of those items from the input list that
350
            are not present in the branch. The two lists will be disjoint
351
            and cover the input list. Either list may be empty, or both if
352
            the input list is empty.
353
        """
354
        #FIXME: should probably do an ancestory check to find all
355
        # merged revisions. This will avoid adding an extra parent
356
        # when say
357
        # experimental 1-1~rc1
358
        # unstable 1-1 1-1~rc1
359
        # Ubuntu 1-1ubuntu1 1-1 1-1~rc1
360
        # where only the first in each list is actually uploaded.
361
        contained = []
362
        not_contained = []
363
        for version in versions:
364
            if self.has_version(version):
365
                contained.append(version)
366
            else:
367
                not_contained.append(version)
368
        return contained, not_contained
369
370
    def missing_versions(self, versions):
371
        """Returns the versions from the list that the branch does not have.
372
373
        Looks at all the versions specified and returns a list of the ones
374
        that are earlier in the list that the last version that is
375
        contained in this branch.
376
377
        :param versions: a list of Version objects to look for in the branch.
378
            May be an empty list.
379
        :return: The subset of versions from the list that are not present
380
            in this branch. May be an empty list.
381
        """
382
        last_contained = self.last_contained_version(versions)
383
        if last_contained is None:
384
            return versions
385
        index = versions.index(last_contained)
386
        return versions[:index]
387
388
    def last_contained_version(self, versions):
389
        """Returns the highest version from the list present in this branch.
390
391
        It assumes that the input list of versions is sorted with the
392
        highest version first.
393
394
        :param versions: a list of Version objects to look for in the branch.
395
            Must be sorted with the highest version first. May be an empty
396
            list.
397
        :return: the highest version that is contained in this branch, or
398
            None if none of the versions are contained within the branch.
399
        """
400
        for version in versions:
401
            if self.has_version(version):
402
                return version
403
        return None
404
405
    def revid_of_version(self, version):
406
        """Returns the revision id corresponding to that version.
407
408
        :param version: the Version object that you wish to retrieve the
409
            revision id of. The Version must be present in the branch.
410
        :return: the revision id corresponding to that version
411
        """
327.1.25 by James Westby
More fallbacks for old tag names.
412
        tag_name = self.tag_name(version)
413
        if self._has_version(self.branch, tag_name):
414
            return self.branch.tags.lookup_tag(tag_name)
415
        debian_tag_name = "debian-" + tag_name
416
        if self._has_version(self.branch, debian_tag_name):
417
            return self.branch.tags.lookup_tag(debian_tag_name)
418
        ubuntu_tag_name = "ubuntu-" + tag_name
419
        if self._has_version(self.branch, ubuntu_tag_name):
420
            return self.branch.tags.lookup_tag(ubuntu_tag_name)
421
        return self.branch.tags.lookup_tag(tag_name)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
422
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
423
    def tag_version(self, version, revid=None):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
424
        """Tags the branch's last revision with the given version.
425
426
        Sets a tag on the last revision of the branch with a tag that refers
427
        to the version provided.
428
429
        :param version: the Version object to derive the tag name from.
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
430
        :param revid: the revid to associate the tag with, or None for the
431
            tip of self.branch.
297.6.1 by Jelmer Vernooij
Print name of created tag in mark-uploaded.
432
        :return: Name of the tag set
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
433
        """
434
        tag_name = self.tag_name(version)
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
435
        if revid is None:
436
            revid = self.branch.last_revision()
437
        self.branch.tags.set_tag(tag_name, revid)
297.6.1 by Jelmer Vernooij
Print name of created tag in mark-uploaded.
438
        return tag_name
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
439
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
440
    def _default_config_for_tree(self, tree):
441
        # FIXME: shouldn't go to configobj directly
613.6.2 by Jelmer Vernooij
Add debian/bzr-builddeb.conf.
442
        for path in ('debian/bzr-builddeb.conf', '.bzr-builddeb/default.conf',):
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
443
            fileid = tree.path2id(path)
444
            if fileid is not None:
613.6.1 by Jelmer Vernooij
Some refactoring.
445
                break
446
        else:
648.1.2 by Vincent Ladeuil
Fix the missed return path
447
            return None, None, None
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
448
        with tree.lock_read():
449
            config = ConfigObj(tree.get_file(path))
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
450
            try:
613.6.1 by Jelmer Vernooij
Some refactoring.
451
                config['BUILDDEB']
452
            except KeyError:
453
                config['BUILDDEB'] = {}
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
454
        return fileid, path, config
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
455
613.6.3 by Jelmer Vernooij
some refactoring.
456
    def _is_tree_native(self, config):
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
457
        if config is not None:
458
            try:
459
                current_value = config['BUILDDEB']['native']
460
            except KeyError:
461
                current_value = False
462
            return current_value == "True"
463
        return False
464
235 by James Westby
Add support for importing native packages.
465
    def is_version_native(self, version):
466
        """Determines whether the given version is native.
467
468
        :param version: the Version object to test. Must be present in
469
            the branch.
470
        :return: True if the version is was recorded as native when
471
            imported, False otherwise.
472
        """
473
        revid = self.revid_of_version(version)
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
474
        rev_tree = self.branch.repository.revision_tree(revid)
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
475
        (config_fileid, config_path, current_config) = self._default_config_for_tree(
476
                rev_tree)
613.6.3 by Jelmer Vernooij
some refactoring.
477
        if self._is_tree_native(current_config):
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
478
            return True
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
479
        rev = self.branch.repository.get_revision(revid)
235 by James Westby
Add support for importing native packages.
480
        try:
481
            prop = rev.properties["deb-native"]
482
            return prop == "True"
483
        except KeyError:
484
            return False
485
578.2.14 by Jelmer Vernooij
Factor out can_pull_from_branch.
486
    def can_pull_from_branch(self, branch, version, md5):
487
        if not branch.has_version(version, md5=md5):
488
            return False
489
490
        # Check that they haven't diverged
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
491
        with branch.branch.lock_read():
578.2.14 by Jelmer Vernooij
Factor out can_pull_from_branch.
492
            graph = branch.branch.repository.get_graph(
493
                    self.branch.repository)
494
            return graph.is_ancestor(self.branch.last_revision(),
495
                    branch.revid_of_version(version))
496
497
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
498
    def branch_to_pull_version_from(self, version, md5):
499
        """Checks whether this upload is a pull from a lesser branch.
500
501
        Looks in all the lesser branches for the given version/md5 pair
502
        in a branch that has not diverged from this.
503
327.1.61 by James Westby
Also allow "higher" branches when looking for branches to pull parts from.
504
        If it is present in another branch that has not diverged this
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
505
        method will return the greatest branch that it is present in,
506
        otherwise it will return None. If it returns a branch then it
507
        indicates that a pull should be done from that branch, rather
508
        than importing the version as a new revision in this branch.
509
510
        :param version: the Version object to look for in the lesser
511
            branches.
512
        :param md5: a String containing the md5 associateed with the
513
            version.
514
        :return: a DistributionBranch object to pull from if that is
515
            what should be done, otherwise None.
516
        """
517
        assert md5 is not None, \
518
            ("It's not a good idea to use branch_to_pull_version_from with "
519
             "md5 == None, as you may pull the wrong revision.")
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
520
        with self.branch.lock_read():
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
521
            for branch in reversed(self.get_lesser_branches()):
578.2.14 by Jelmer Vernooij
Factor out can_pull_from_branch.
522
                if self.can_pull_from_branch(branch, version, md5):
523
                    return branch
327.1.61 by James Westby
Also allow "higher" branches when looking for branches to pull parts from.
524
            for branch in self.get_greater_branches():
578.2.14 by Jelmer Vernooij
Factor out can_pull_from_branch.
525
                if self.can_pull_from_branch(branch, version, md5):
526
                    return branch
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
527
            return None
528
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
529
    def can_pull_upstream_from_branch(self, branch, package, version,
530
            upstream_tarballs=None):
531
        """Check if a version can be pulled from another branch into this one.
532
533
        :param branch: Branch with upstream version
534
        :param package: Package name
535
        :param version: Package version
536
        :param upstream_tarballs: Required upstream tarballs (optional)
537
        """
578.2.9 by Jelmer Vernooij
Remove unnecessary has_upstream_version call.
538
        if not branch.pristine_upstream_source.has_version(package, version,
539
                tarballs=upstream_tarballs):
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
540
            return False
541
542
        up_branch = self.pristine_upstream_branch
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
543
        with up_branch.lock_read():
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
544
            # Check that they haven't diverged
545
            other_up_branch = branch.pristine_upstream_branch
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
546
            with other_up_branch.lock_read():
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
547
                graph = other_up_branch.repository.get_graph(
548
                        up_branch.repository)
641.1.1 by Jelmer Vernooij
Cope with multiple upstream tarballs in can_pull_upstream_from_branch.
549
                pristine_upstream_revids = branch.pristine_upstream_source.version_as_revisions(
550
                        package, version, tarballs=upstream_tarballs)
551
                for (component, pristine_upstream_revid) in pristine_upstream_revids.iteritems():
552
                    if not graph.is_ancestor(up_branch.last_revision(),
553
                            pristine_upstream_revid):
554
                        return False
555
                return True
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
556
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
557
    def branch_to_pull_upstream_from(self, package, version, upstream_tarballs):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
558
        """Checks whether this upstream is a pull from a lesser branch.
559
327.1.61 by James Westby
Also allow "higher" branches when looking for branches to pull parts from.
560
        Looks in all the other upstream branches for the given
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
561
        version/md5 pair in a branch that has not diverged from this.
562
        If it is present in a lower branch this method will return the
563
        greatest branch that it is present in that has not diverged,
564
        otherwise it will return None. If it returns a branch then it
565
        indicates that a pull should be done from that branch, rather
566
        than importing the upstream as a new revision in this branch.
567
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
568
        :param version: the upstream version to use when searching in the 
569
            lesser branches.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
570
        :return: a DistributionBranch object to pull the upstream from
571
            if that is what should be done, otherwise None.
572
        """
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
573
        assert isinstance(version, str)
578.2.6 by Jelmer Vernooij
Factor out can_pull_upstream_from_branch.
574
        for branch in reversed(self.get_lesser_branches()):
575
            if self.can_pull_upstream_from_branch(branch, package, version,
576
                    upstream_tarballs):
577
                return branch
578
        for branch in self.get_greater_branches():
579
            if self.can_pull_upstream_from_branch(branch, package, version,
580
                    upstream_tarballs):
581
                return branch
582
        return None
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
583
584
    def get_parents(self, versions):
585
        """Return the list of parents for a specific version.
586
587
        This method returns the list of revision ids that should be parents
443.1.1 by Jelmer Vernooij
Pass version -> revision map into UpstreamBranchSource.
588
        for importing a specific package version. The specific package version
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
589
        is the first element of the list of versions passed.
590
591
        The parents are determined by looking at the other versions in the
592
        passed list and examining which of the branches (if any) they are
593
        already present in.
594
595
        You should probably use get_parents_with_upstream rather than
596
        this method.
597
598
        :param versions: a list of Version objects, the first item of
599
            which is the version of the package that is currently being
600
            imported.
601
        :return: a list of tuples of (DistributionBranch, version,
602
            revision id). The revision ids should all be parents of the
603
            revision that imports the specified version of the package.
604
            The versions are the versions that correspond to that revision
605
            id. The DistributionBranch is the branch that contains that
606
            version.
607
        """
608
        assert len(versions) > 0, "Need a version to import"
609
        mutter("Getting parents of %s" % str(versions))
610
        missing_versions = self.missing_versions(versions)
611
        mutter("Versions we don't have are %s" % str(missing_versions))
612
        last_contained_version = self.last_contained_version(versions)
613
        parents = []
614
        if last_contained_version is not None:
615
            assert last_contained_version != versions[0], \
616
                "Reupload of a version?"
617
            mutter("The last versions we do have is %s" \
618
                    % str(last_contained_version))
619
            parents = [(self, last_contained_version,
620
                    self.revid_of_version(last_contained_version))]
621
        else:
622
            mutter("We don't have any of those versions")
643.1.2 by Jelmer Vernooij
Some refactoring.
623
        for branch in list(reversed(self.get_lesser_branches())) + self.get_greater_branches():
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
624
            merged, missing_versions = \
625
                branch.contained_versions(missing_versions)
626
            if merged:
627
                revid = branch.revid_of_version(merged[0])
628
                parents.append((branch, merged[0], revid))
643.1.2 by Jelmer Vernooij
Some refactoring.
629
                mutter("Adding merge from related branch of %s for version %s"
321.1.3 by James Westby
Drop the requirement for DistributionBranch to have a name.
630
                        % (revid, str(merged[0])))
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
631
                #FIXME: should this really be here?
643.1.2 by Jelmer Vernooij
Some refactoring.
632
                self._fetch_from_branch(branch, revid)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
633
        return parents
634
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
635
    def pull_upstream_from_branch(self, pull_branch, package, version):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
636
        """Pulls an upstream version from a branch.
637
638
        Given a DistributionBranch and a version number this method
639
        will pull the upstream part of the given version from the
640
        branch in to this. The upstream version must be present
641
        in the DistributionBranch, and it is assumed that the md5
642
        matches.
643
644
        It sets the necessary tags so that the pulled version is
645
        recognised as being part of this branch.
646
647
        :param pull_branch: the DistributionBranch to pull from.
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
648
        :param version: the upstream version string
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
649
        """
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
650
        assert isinstance(version, str)
613.5.7 by Jelmer Vernooij
Support extracting pristine tarball versions with multiple upstream revisions.
651
        pull_revisions = pull_branch.pristine_upstream_source.version_as_revisions(
652
            package, version)
643.1.2 by Jelmer Vernooij
Some refactoring.
653
        for (component, pull_revision) in pull_revisions.iteritems():
654
            mutter("Fetching upstream part %s of %s from revision %s" % \
655
                    (component, version, pull_revision))
656
            assert self.pristine_upstream_tree is not None, \
657
                "Can't pull upstream with no tree"
658
            self.pristine_upstream_branch.pull(pull_branch.pristine_upstream_branch,
659
                    stop_revision=pull_revision)
660
            self.pristine_upstream_source.tag_version(version, pull_revision)
661
            self.branch.fetch(self.pristine_upstream_branch, last_revision=pull_revision)
662
            self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
663
        checkout_upstream_version(self.pristine_upstream_tree,
664
            package, version, pull_revisions)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
665
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
666
    def pull_version_from_branch(self, pull_branch, package, version, native=False):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
667
        """Pull a version from a particular branch.
668
669
        Given a DistributionBranch and a version number this method
670
        will pull the given version from the branch in to this. The
671
        version must be present in the DistributionBranch, and it
672
        is assumed that the md5 matches.
673
674
        It will also pull in any upstream part that is needed to
675
        the upstream branch. It is assumed that the md5 matches
676
        here as well. If the upstream version must be present in
677
        at least one of the upstream branches.
678
679
        It sets the necessary tags on the revisions so they are
680
        recongnised in this branch as well.
681
682
        :param pull_branch: the DistributionBranch to pull from.
683
        :param version: the Version to pull.
234 by James Westby
Support basic importing of native packages.
684
        :param native: whether it is a native version that is being
685
            imported.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
686
        """
687
        pull_revision = pull_branch.revid_of_version(version)
321.1.3 by James Westby
Drop the requirement for DistributionBranch to have a name.
688
        mutter("already has version %s so pulling from revision %s"
689
                % (str(version), pull_revision))
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
690
        assert self.tree is not None, "Can't pull branch with no tree"
691
        self.tree.pull(pull_branch.branch, stop_revision=pull_revision)
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
692
        self.tag_version(version, revid=pull_revision)
578.2.9 by Jelmer Vernooij
Remove unnecessary has_upstream_version call.
693
        if not native and not self.pristine_upstream_source.has_version(package, version.upstream_version):
694
            if pull_branch.pristine_upstream_source.has_version(package, version.upstream_version):
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
695
                self.pull_upstream_from_branch(pull_branch,
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
696
                    package, version.upstream_version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
697
            else:
327.5.4 by James Westby
Merge upstream branches when necessary.
698
                assert False, ("Can't find the needed upstream part "
699
                        "for version %s" % version)
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
700
        if (native and self.pristine_upstream_branch.last_revision() == NULL_REVISION
701
            and pull_branch.pristine_upstream_branch.last_revision() != NULL_REVISION):
266.1.30 by James Westby
Initialise the upstream branch when native, if the package wasn't alway native.
702
            # in case the package wasn't native before then we pull
703
            # the upstream. These checks may be a bit restrictive.
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
704
            self.pristine_upstream_tree.pull(pull_branch.pristine_upstream_branch)
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
705
            pull_branch.pristine_upstream_branch.tags.merge_to(
706
                    self.pristine_upstream_branch.tags)
234 by James Westby
Support basic importing of native packages.
707
        elif native:
708
            mutter("Not checking for upstream as it is a native package")
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
709
        else:
710
            mutter("Not importing the upstream part as it is already "
711
                    "present in the upstream branch")
712
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
713
    def get_parents_with_upstream(self, package, version, versions,
578.2.12 by Jelmer Vernooij
Pass tarballs on to get_parents_with_upstream.
714
            tarballs, force_upstream_parent=False):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
715
        """Get the list of parents including any upstream parents.
716
717
        Further to get_parents this method includes any upstream parents
718
        that are needed. An upstream parent is needed if none of
719
        the other parents include the upstream version. The needed
720
        upstream must already present in the upstream branch before
721
        calling this method.
722
723
        If force_upstream_parent is True then the upstream parent will
724
        be included, even if another parent is already using that
725
        upstream. This is for use in cases where the .orig.tar.gz
578.2.12 by Jelmer Vernooij
Pass tarballs on to get_parents_with_upstream.
726
        is different in two distributions.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
727
728
        :param version: the Version that we are currently importing.
729
        :param versions: the list of Versions that are ancestors of
730
            version, including version itself. Sorted with the latest
731
            versions first, so version must be the first entry.
732
        :param force_upstream_parent: if True then an upstream parent
733
            will be added as the first parent, regardless of what the
734
            other parents are.
735
        :return: a list of revision ids that should be the parents when
736
            importing the specified revision.
737
        """
738
        assert version == versions[0], \
739
            "version is not the first entry of versions"
740
        parents = self.get_parents(versions)
741
        need_upstream_parent = True
742
        if not force_upstream_parent:
743
            for parent_pair in parents:
744
                if (parent_pair[1].upstream_version == \
745
                        version.upstream_version):
746
                    need_upstream_parent = False
747
                    break
748
        real_parents = [p[2] for p in parents]
749
        if need_upstream_parent:
613.5.8 by Jelmer Vernooij
Some reformatting.
750
            upstream_revids = self.pristine_upstream_source.version_as_revisions(
751
                package, version.upstream_version, tarballs)
613.5.7 by Jelmer Vernooij
Support extracting pristine tarball versions with multiple upstream revisions.
752
            def key(a):
753
                if a is None:
754
                    return None
755
                return a
756
            for component in sorted(upstream_revids.keys(), key=key):
757
                if len(real_parents) > 0:
758
                    real_parents.insert(1, upstream_revids[component])
759
                else:
760
                    real_parents = [upstream_revids[component]]
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
761
        return real_parents
762
643.1.2 by Jelmer Vernooij
Some refactoring.
763
    def _fetch_upstream_to_branch(self, imported_revids):
368.1.4 by Muharem Hrnjadovic
Fixed typo.
764
        """Fetch the revision from the upstream branch in to the packaging one.
266.1.8 by James Westby
"Fix" fetching between two locked branches which share a repository.
765
        """
365.1.5 by Muharem Hrnjadovic
Removed superfluous checks (James' review comments).
766
        # Make sure we see any revisions added by the upstream branch
767
        # since self.tree was locked.
768
        self.branch.repository.refresh_data()
643.1.2 by Jelmer Vernooij
Some refactoring.
769
        for (component, tag, revid) in imported_revids:
770
            self.branch.fetch(self.pristine_upstream_branch, last_revision=revid)
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
771
        self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
266.1.8 by James Westby
"Fix" fetching between two locked branches which share a repository.
772
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
773
    def import_upstream(self, upstream_part, package, version, upstream_parents,
570.2.23 by Jelmer Vernooij
Move component tarball importing to pristinetarsource.
774
            upstream_tarballs, upstream_branch=None,
613.5.5 by Jelmer Vernooij
More refactoring.
775
            upstream_revisions=None, timestamp=None, author=None,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
776
            file_ids_from=None):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
777
        """Import an upstream part on to the upstream branch.
778
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
779
        This imports the upstream part of the code and places it on to
780
        the upstream branch, setting the necessary tags.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
781
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
782
        :param upstream_part: the path of a directory containing the
783
            unpacked upstream part of the source package.
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
784
        :param version: upstream version that is being imported
235.1.2 by James Westby
Handle more transitions between native and non-native.
785
        :param upstream_parents: the parents to give the upstream revision
327.5.1 by James Westby
Tweaks for auto import.
786
        :param timestamp: a tuple of (timestamp, timezone) to use for
787
            the commit, or None to use the current time.
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
788
        :return: list with (component, tag, revid) tuples
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
789
        """
790
        # Should we just dump the upstream part on whatever is currently
791
        # there, or try and pull all of the other upstream versions
792
        # from lesser branches first? For now we'll just dump it on.
793
        # TODO: this method needs a lot of work for when we will make
794
        # the branches writeable by others.
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
795
        assert isinstance(version, str)
613.5.9 by Jelmer Vernooij
Fix iter_versions.
796
        mutter("Importing upstream version %s from %s with parents %r" \
797
                % (version, upstream_part, upstream_parents))
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
798
        assert self.pristine_upstream_tree is not None, \
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
799
            "Can't import upstream with no tree"
229 by James Westby
Use file ids from other trees.
800
        other_branches = self.get_other_branches()
578.2.22 by Jelmer Vernooij
Reintroduce import_component_tarball.
801
        ret = []
802
        for (tarball, component, md5) in upstream_tarballs:
613.5.9 by Jelmer Vernooij
Fix iter_versions.
803
            parents = upstream_parents.get(component, [])
613.5.5 by Jelmer Vernooij
More refactoring.
804
            if upstream_revisions is not None:
805
                revid = upstream_revisions[component]
806
            else:
807
                revid = None
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
808
            upstream_trees = [o.pristine_upstream_branch.basis_tree()
809
                for o in other_branches]
810
            target_tree = None
811
            if upstream_branch is not None:
613.5.5 by Jelmer Vernooij
More refactoring.
812
                if revid is None:
813
                    # FIXME: This is wrong for component tarballs
814
                    revid = upstream_branch.last_revision()
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
815
                self.pristine_upstream_branch.fetch(
816
                        upstream_branch, last_revision=revid)
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
817
                upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
613.5.9 by Jelmer Vernooij
Fix iter_versions.
818
                parents.append(revid)
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
819
                target_tree = self.pristine_upstream_branch.repository.revision_tree(
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
820
                        revid)
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
821
            if file_ids_from is not None:
822
                upstream_trees = file_ids_from + upstream_trees
823
            if self.tree:
824
                self_tree = self.tree
825
                self_tree.lock_write() # might also be upstream tree for dh_make
826
            else:
827
                self_tree = self.branch.basis_tree()
828
                self_tree.lock_read()
613.5.9 by Jelmer Vernooij
Fix iter_versions.
829
            if len(parents) > 0:
830
                parent_revid = parents[0]
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
831
            else:
832
                parent_revid = NULL_REVISION
833
            self.pristine_upstream_tree.pull(self.pristine_upstream_tree.branch,
834
                overwrite=True, stop_revision=parent_revid)
835
            if component is None:
836
                path = upstream_part
837
            else:
838
                path = os.path.join(upstream_part, component)
839
            try:
840
                import_dir(self.pristine_upstream_tree, path,
841
                        file_ids_from=[self_tree] + upstream_trees,
842
                        target_tree=target_tree)
843
            finally:
844
                self_tree.unlock()
613.5.11 by Jelmer Vernooij
Support importing and building packages with multiple upstream
845
            if component is None:
846
                exclude = [tb[1] for tb in upstream_tarballs if tb[1] is not None]
847
            else:
848
                exclude = []
578.2.22 by Jelmer Vernooij
Reintroduce import_component_tarball.
849
            (tag, revid) = self.pristine_upstream_source.import_component_tarball(
613.5.9 by Jelmer Vernooij
Fix iter_versions.
850
                package, version, self.pristine_upstream_tree, parents,
613.5.11 by Jelmer Vernooij
Support importing and building packages with multiple upstream
851
                component, md5, tarball, author=author, timestamp=timestamp,
852
                exclude=exclude)
613.5.3 by Jelmer Vernooij
More refactoring.
853
            self.pristine_upstream_branch.generate_revision_history(revid)
578.2.22 by Jelmer Vernooij
Reintroduce import_component_tarball.
854
            ret.append((component, tag, revid))
570.2.24 by Jelmer Vernooij
Fix test.
855
            self.branch.fetch(self.pristine_upstream_branch)
856
            self.branch.tags.set_tag(tag, revid)
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
857
        return ret
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
858
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
859
    def import_upstream_tarballs(self, tarballs, package, version, parents,
613.5.5 by Jelmer Vernooij
More refactoring.
860
        upstream_branch=None, upstream_revisions=None):
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
861
        """Import an upstream part to the upstream branch.
862
570.2.17 by Jelmer Vernooij
Pass along component with tarballs.
863
        :param tarballs: List of tarballs / components to extract
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
864
        :param version: The upstream version to import.
447.1.5 by Robert Collins
import-upstream sets the most recent previous tarballs as a parent.
865
        :param parents: The tarball-branch parents to use for the import.
866
            If an upstream branch is supplied, its automatically added to
867
            parents.
868
        :param upstream_branch: An upstream branch to associate with the
869
            tarball.
613.5.5 by Jelmer Vernooij
More refactoring.
870
        :param upstream_revisions: Upstream revision ids dictionary
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
871
        :param md5sum: hex digest of the md5sum of the tarball, if known.
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
872
        :return: list with (component, tag, revid) tuples
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
873
        """
570.2.5 by Jelmer Vernooij
Pass tarballs along further.
874
        tarball_dir = self._extract_tarballs_to_tempdir(tarballs)
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
875
        try:
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
876
            return self.import_upstream(tarball_dir, package, version, parents,
570.2.4 by Jelmer Vernooij
pass multiple tarballs around in more places.
877
                tarballs,
451.6.1 by Jelmer Vernooij
Add -r support to import-upstream.
878
                upstream_branch=upstream_branch,
613.5.5 by Jelmer Vernooij
More refactoring.
879
                upstream_revisions=upstream_revisions)
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
880
        finally:
881
            shutil.rmtree(tarball_dir)
882
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
883
    def _mark_native_config(self, native):
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
884
        poss_native_tree = self.branch.basis_tree()
648.1.1 by Vincent Ladeuil
Avoid locking issues with _mark_taive_config
885
        (config_fileid, config_relpath,
886
         current_config) = self._default_config_for_tree(poss_native_tree)
613.6.5 by Jelmer Vernooij
Move .bzr-builddeb/default.conf to debian/bzr-builddeb.conf. LP:
887
        current_native = self._is_tree_native(current_config)
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
888
        if current_config is not None:
889
            # Add that back to the current tree
648.1.1 by Vincent Ladeuil
Avoid locking issues with _mark_taive_config
890
            current_config.filename = self.tree.abspath(config_relpath)
613.6.5 by Jelmer Vernooij
Move .bzr-builddeb/default.conf to debian/bzr-builddeb.conf. LP:
891
            dir_path = osutils.dirname(current_config.filename)
892
            if not os.path.exists(dir_path):
893
                os.mkdir(dir_path)
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
894
            current_config.write()
648.1.1 by Vincent Ladeuil
Avoid locking issues with _mark_taive_config
895
            dirname = osutils.dirname(config_relpath)
613.6.5 by Jelmer Vernooij
Move .bzr-builddeb/default.conf to debian/bzr-builddeb.conf. LP:
896
            dir_id = poss_native_tree.path2id(dirname)
648.1.1 by Vincent Ladeuil
Avoid locking issues with _mark_taive_config
897
            self.tree.add([dirname, config_relpath],
898
                          ids=[dir_id, config_fileid])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
899
        if native != current_native:
900
            if current_config is None:
901
                needs_add = True
902
                if native:
903
                    current_config = ConfigObj()
904
                    current_config['BUILDDEB'] = {}
905
            if current_config is not None:
906
                if native:
907
                    current_config['BUILDDEB']['native'] = True
908
                else:
909
                    del current_config['BUILDDEB']['native']
910
                    if len(current_config['BUILDDEB']) == 0:
911
                        del current_config['BUILDDEB']
912
                if len(current_config) == 0:
913
                    self.tree.remove(['.bzr-builddeb',
613.6.5 by Jelmer Vernooij
Move .bzr-builddeb/default.conf to debian/bzr-builddeb.conf. LP:
914
                            '.bzr-builddeb/default.conf',
915
                            'debian/bzr-builddeb.conf'],
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
916
                            keep_files=False)
917
                else:
613.6.6 by jelmer at samba
Don't create empty .bzr-builddeb directory.
918
                    current_config.filename = os.path.join(
919
                        self.tree.basedir, 'debian', 'bzr-builddeb.conf')
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
920
                    current_config.write()
921
                    if needs_add:
613.6.5 by Jelmer Vernooij
Move .bzr-builddeb/default.conf to debian/bzr-builddeb.conf. LP:
922
                        self.tree.add(['debian', 'debian/bzr-builddeb.conf'])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
923
235 by James Westby
Add support for importing native packages.
924
    def import_debian(self, debian_part, version, parents, md5,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
925
            native=False, timestamp=None, file_ids_from=None):
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
926
        """Import the debian part of a source package.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
927
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
928
        :param debian_part: the path of a directory containing the unpacked
929
            source package.
930
        :param version: the Version of the source package.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
931
        :param parents: a list of revision ids that should be the
932
            parents of the imported revision.
933
        :param md5: the md5 sum reported by the .dsc for
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
934
            the .diff.gz part of this source package.
327.5.1 by James Westby
Tweaks for auto import.
935
        :param native: whether the package is native.
936
        :param timestamp: a tuple of (timestamp, timezone) to use for
937
            the commit, or None to use the current values.
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
938
        """
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
939
        mutter("Importing debian part for version %s from %s, with parents "
940
                "%s" % (str(version), debian_part, str(parents)))
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
941
        assert self.tree is not None, "Can't import with no tree"
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
942
        # First we move the branch to the first parent
943
        if parents:
237 by James Westby
Don't override the tip of a branch when importing.
944
            if self.branch.last_revision() == NULL_REVISION:
945
                parent_revid = parents[0]
946
                self.tree.pull(self.tree.branch, overwrite=True,
947
                        stop_revision=parent_revid)
948
            elif parents[0] != self.branch.last_revision():
949
                mutter("Adding current tip as parent: %s"
950
                        % self.branch.last_revision())
951
                parents.insert(0, self.branch.last_revision())
242 by James Westby
Don't try and commit with no parents if it's not the initial commit.
952
        elif self.branch.last_revision() != NULL_REVISION:
953
            # We were told to import with no parents. That's not
954
            # right, so import with the current parent. Should
955
            # perhaps be fixed in the methods to determine the parents.
956
            mutter("Told to import with no parents. Adding current tip "
957
                   "as the single parent")
958
            parents = [self.branch.last_revision()]
229 by James Westby
Use file ids from other trees.
959
        other_branches = self.get_other_branches()
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
960
        debian_trees = [o.branch.basis_tree() for o in other_branches]
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
961
        parent_trees = []
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
962
        if file_ids_from is not None:
963
            parent_trees = file_ids_from[:]
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
964
        for parent in parents:
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
965
            parent_trees.append(self.branch.repository.revision_tree(
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
966
                        parent))
967
        import_dir(self.tree, debian_part,
968
                file_ids_from=parent_trees + debian_trees)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
969
        rules_path = os.path.join(self.tree.basedir, 'debian', 'rules')
970
        if os.path.isfile(rules_path):
971
            os.chmod(rules_path,
972
                     (stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|
973
                      stat.S_IROTH|stat.S_IXOTH))
974
        self.tree.set_parent_ids(parents)
332 by James Westby
Refactor extracting commit information from the changelog.
975
        changelog_path = os.path.join(self.tree.basedir, 'debian',
976
                'changelog')
977
        if os.path.exists(changelog_path):
662.1.1 by Vincent Ladeuil
Safely decode changelog to cope with recent python-debian enforcing utf-8
978
            changelog = self.get_changelog_from_source(
979
                self.tree.basedir, max_blocks=1)
329 by James Westby
Add bugs fixed information based on changelog.
980
        message, authors, thanks, bugs = \
332 by James Westby
Refactor extracting commit information from the changelog.
981
                get_commit_info_from_changelog(changelog, self.branch)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
982
        if message is None:
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
983
            message = 'Import packaging changes for version %s' % \
984
                        (str(version),)
561.1.2 by Jelmer Vernooij
Move pristine tar bits out of import_dsc.
985
        revprops={"deb-md5": md5}
235 by James Westby
Add support for importing native packages.
986
        if native:
987
            revprops['deb-native'] = "True"
332 by James Westby
Refactor extracting commit information from the changelog.
988
        if authors:
327.3.1 by James Westby
Record extra authors in import-dsc based on what is in the changelog
989
            revprops['authors'] = "\n".join(authors)
332 by James Westby
Refactor extracting commit information from the changelog.
990
        if thanks:
327.3.1 by James Westby
Record extra authors in import-dsc based on what is in the changelog
991
            revprops['deb-thanks'] = "\n".join(thanks)
329 by James Westby
Add bugs fixed information based on changelog.
992
        if bugs:
993
            revprops['bugs'] = "\n".join(bugs)
327.5.1 by James Westby
Tweaks for auto import.
994
        timezone = None
995
        if timestamp is not None:
996
            timezone = timestamp[1]
997
            timestamp = timestamp[0]
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
998
        self._mark_native_config(native)
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
999
        revid = self.tree.commit(message, revprops=revprops, timestamp=timestamp,
327.5.1 by James Westby
Tweaks for auto import.
1000
                timezone=timezone)
433.2.3 by James Westby
Ensure that the tags are set on the correct revisions.
1001
        self.tag_version(version, revid=revid)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1002
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1003
    def upstream_parents(self, package, versions, version):
235.1.2 by James Westby
Handle more transitions between native and non-native.
1004
        """Get the parents for importing a new upstream.
1005
1006
        The upstream parents will be the last upstream version,
1007
        except for some cases when the last version was native.
1008
1009
        :return: the list of revision ids to use as parents when
1010
            importing the specified upstream version.
1011
        """
1012
        parents = []
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1013
        first_parent = self.pristine_upstream_branch.last_revision()
235.1.2 by James Westby
Handle more transitions between native and non-native.
1014
        if first_parent != NULL_REVISION:
1015
            parents = [first_parent]
1016
        last_contained_version = self.last_contained_version(versions)
1017
        if last_contained_version is not None:
1018
            # If the last version was native, and was not from the same
1019
            # upstream as a non-native version (i.e. it wasn't a mistaken
1020
            # native -2 version), then we want to add an extra parent.
1021
            if (self.is_version_native(last_contained_version)
578.2.9 by Jelmer Vernooij
Remove unnecessary has_upstream_version call.
1022
                and not self.pristine_upstream_source.has_version(package,
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1023
                    last_contained_version.upstream_version)):
235.1.2 by James Westby
Handle more transitions between native and non-native.
1024
                revid = self.revid_of_version(last_contained_version)
1025
                parents.append(revid)
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1026
                self.pristine_upstream_branch.fetch(self.branch,
235.1.2 by James Westby
Handle more transitions between native and non-native.
1027
                        last_revision=revid)
327.5.4 by James Westby
Merge upstream branches when necessary.
1028
        pull_parents = self.get_parents(versions)
1029
        if ((first_parent == NULL_REVISION and len(pull_parents) > 0)
1030
                or len(pull_parents) > 1):
1031
            if first_parent == NULL_REVISION:
235.1.2 by James Westby
Handle more transitions between native and non-native.
1032
                pull_branch = pull_parents[0][0]
1033
                pull_version = pull_parents[0][1]
327.5.4 by James Westby
Merge upstream branches when necessary.
1034
            else:
1035
                pull_branch = pull_parents[1][0]
1036
                pull_version = pull_parents[1][1]
1037
            if not pull_branch.is_version_native(pull_version):
613.5.7 by Jelmer Vernooij
Support extracting pristine tarball versions with multiple upstream revisions.
1038
                pull_revids = pull_branch.pristine_upstream_source.version_as_revisions(
570.2.13 by Jelmer Vernooij
Use PristineTarSource functionality.
1039
                    package, pull_version.upstream_version)
613.5.7 by Jelmer Vernooij
Support extracting pristine tarball versions with multiple upstream revisions.
1040
                if pull_revids.keys() != [None]:
1041
                    raise MultipleUpstreamTarballsNotSupported()
1042
                pull_revid = pull_revids[None]
570.2.13 by Jelmer Vernooij
Use PristineTarSource functionality.
1043
                mutter("Initialising upstream from %s, version %s",
1044
                    str(pull_branch), str(pull_version))
1045
                parents.append(pull_revid)
1046
                self.pristine_upstream_branch.fetch(
1047
                        pull_branch.pristine_upstream_branch,
1048
                        last_revision=pull_revid)
1049
                pull_branch.pristine_upstream_branch.tags.merge_to(
1050
                        self.pristine_upstream_branch.tags)
613.5.9 by Jelmer Vernooij
Fix iter_versions.
1051
        # FIXME: What about other versions ?
1052
        return { None: parents }
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1053
662.1.1 by Vincent Ladeuil
Safely decode changelog to cope with recent python-debian enforcing utf-8
1054
    def get_changelog_from_source(self, dir, max_blocks=None):
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1055
        cl_filename = os.path.join(dir, "debian", "changelog")
662.1.1 by Vincent Ladeuil
Safely decode changelog to cope with recent python-debian enforcing utf-8
1056
        content = open(cl_filename).read()
1057
        # Older versions of python-debian were accepting various encodings in
1058
        # the changelog. This is not true with 0.1.20ubuntu2 at least which
1059
        # force an 'utf-8' encoding. This leads to failures when trying to
1060
        # parse old changelogs. Using safe_decode() below will fallback to
1061
        # iso-8859-1 (latin_1) in this case.
1062
        content = safe_decode(content)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1063
        cl = Changelog()
662.1.1 by Vincent Ladeuil
Safely decode changelog to cope with recent python-debian enforcing utf-8
1064
        cl.parse_changelog(content, strict=False, max_blocks=max_blocks)
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1065
        return cl
1066
643.1.2 by Jelmer Vernooij
Some refactoring.
1067
    def _fetch_from_branch(self, branch, revid):
1068
        branch.branch.tags.merge_to(self.branch.tags)
1069
        self.branch.fetch(branch.branch, last_revision=revid)
1070
        if self.pristine_upstream_branch.last_revision() == NULL_REVISION:
1071
            self.pristine_upstream_tree.pull(branch.pristine_upstream_branch)
1072
            branch.pristine_upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
1073
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1074
    def _import_normal_package(self, package, version, versions, debian_part, md5,
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1075
            upstream_part, upstream_tarballs, timestamp=None, author=None,
1076
            file_ids_from=None, pull_debian=True):
570.2.2 by Jelmer Vernooij
Add docstring for _do_import_package.
1077
        """Import a source package.
1078
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1079
        :param package: Package name
570.2.2 by Jelmer Vernooij
Add docstring for _do_import_package.
1080
        :param version: Full Debian version
1081
        :param versions: Safe versions from changelog
1082
        :param debian_part: Path to extracted directory with Debian changes
1083
        :param unextracted_debian_md5: MD5 sum of unextracted Debian diff/tarball
1084
        :param upstream_part: Extracted upstream directory
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1085
        :param upstream_tarballs: List of tuples with (upstream tarfile, md5sum)
570.2.2 by Jelmer Vernooij
Add docstring for _do_import_package.
1086
        :param timestamp: Version timestamp according to changelog
1087
        :param author: Author according to changelog
1088
        :param file_ids_from: Sequence of trees to take file ids from
1089
        :param pull_debian: Whether to pull from the Debian branch
1090
        """
405.1.5 by James Westby
Add a way to prevent pulling even if it can be done.
1091
        pull_branch = None
1092
        if pull_debian:
1093
            pull_branch = self.branch_to_pull_version_from(version, md5)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1094
        if pull_branch is not None:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1095
            if (self.branch_to_pull_upstream_from(package,
1096
                    version.upstream_version, upstream_tarballs)
327.5.4 by James Westby
Merge upstream branches when necessary.
1097
                    is None):
1098
                pull_branch = None
1099
        if pull_branch is not None:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1100
            self.pull_version_from_branch(pull_branch, package, version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1101
        else:
1102
            # We need to import at least the diff, possibly upstream.
1103
            # Work out if we need the upstream part first.
1104
            imported_upstream = False
578.2.1 by Jelmer Vernooij
Rename fetch_tarball to fetch_tarballs to reflect reality.
1105
            if not self.pristine_upstream_source.has_version(package,
1106
                    version.upstream_version):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1107
                up_pull_branch = \
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1108
                    self.branch_to_pull_upstream_from(package, version.upstream_version,
570.2.4 by Jelmer Vernooij
pass multiple tarballs around in more places.
1109
                            upstream_tarballs)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1110
                if up_pull_branch is not None:
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
1111
                    self.pull_upstream_from_branch(up_pull_branch,
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1112
                            package, version.upstream_version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1113
                else:
1114
                    imported_upstream = True
1115
                    # Check whether we should pull first if this initialises
1116
                    # from another branch:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1117
                    upstream_parents = self.upstream_parents(package, versions,
351 by Jelmer Vernooij
Make upstream-version oriented methods take just upstream versions.
1118
                            version.upstream_version)
643.1.2 by Jelmer Vernooij
Some refactoring.
1119
                    imported_revids = self.import_upstream(upstream_part,
570.2.22 by Jelmer Vernooij
More work on separate methods for importing tarballs.
1120
                            package, version.upstream_version,
570.2.4 by Jelmer Vernooij
pass multiple tarballs around in more places.
1121
                            upstream_parents,
1122
                            upstream_tarballs=upstream_tarballs,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
1123
                            timestamp=timestamp, author=author,
643.1.2 by Jelmer Vernooij
Some refactoring.
1124
                            file_ids_from=file_ids_from)
1125
                    self._fetch_upstream_to_branch(imported_revids)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1126
            else:
1127
                mutter("We already have the needed upstream part")
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1128
            parents = self.get_parents_with_upstream(package, version, versions,
578.2.12 by Jelmer Vernooij
Pass tarballs on to get_parents_with_upstream.
1129
                    upstream_tarballs, force_upstream_parent=imported_upstream)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1130
            # Now we have the list of parents we need to import the .diff.gz
327.5.1 by James Westby
Tweaks for auto import.
1131
            self.import_debian(debian_part, version, parents, md5,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
1132
                    timestamp=timestamp, file_ids_from=file_ids_from)
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1133
234 by James Westby
Support basic importing of native packages.
1134
    def get_native_parents(self, version, versions):
1135
        last_contained_version = self.last_contained_version(versions)
1136
        if last_contained_version is None:
266.1.31 by James Westby
Include merges when looking for parents of a native version.
1137
            parents = []
234 by James Westby
Support basic importing of native packages.
1138
        else:
266.1.31 by James Westby
Include merges when looking for parents of a native version.
1139
            parents = [self.revid_of_version(last_contained_version)]
1140
        missing_versions = self.missing_versions(versions)
643.1.2 by Jelmer Vernooij
Some refactoring.
1141
        for branch in list(reversed(self.get_lesser_branches())) + self.get_greater_branches():
1142
            merged, missing_versions = \
1143
                branch.contained_versions(missing_versions)
1144
            if merged:
1145
                revid = branch.revid_of_version(merged[0])
1146
                parents.append(revid)
1147
                #FIXME: should this really be here?
1148
                self._fetch_from_branch(branch, revid)
266.1.33 by James Westby
Always use the tip as the first parent when importing native packages.
1149
        if (self.branch.last_revision() != NULL_REVISION
1150
                and not self.branch.last_revision() in parents):
1151
            parents.insert(0, self.branch.last_revision())
266.1.31 by James Westby
Include merges when looking for parents of a native version.
1152
        return parents
1153
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1154
    def _import_native_package(self, package, version, versions, debian_part, md5,
405.1.5 by James Westby
Add a way to prevent pulling even if it can be done.
1155
            timestamp=None, file_ids_from=None, pull_debian=True):
1156
        pull_branch = None
1157
        if pull_debian:
1158
            pull_branch = self.branch_to_pull_version_from(version, md5)
234 by James Westby
Support basic importing of native packages.
1159
        if pull_branch is not None:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1160
            self.pull_version_from_branch(pull_branch, package, version, native=True)
234 by James Westby
Support basic importing of native packages.
1161
        else:
1162
            parents = self.get_native_parents(version, versions)
235 by James Westby
Add support for importing native packages.
1163
            self.import_debian(debian_part, version, parents, md5,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
1164
                    native=True, timestamp=timestamp,
1165
                    file_ids_from=file_ids_from)
234 by James Westby
Support basic importing of native packages.
1166
266.1.16 by James Westby
Handle invalid version numbers in the changelog by ignoring them.
1167
    def _get_safe_versions_from_changelog(self, cl):
1168
        versions = []
1169
        for block in cl._blocks:
1170
            try:
1171
                versions.append(block.version)
1172
            except VersionError:
1173
                break
1174
        return versions
1175
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
1176
    def import_package(self, dsc_filename, use_time_from_changelog=True,
405.1.5 by James Westby
Add a way to prevent pulling even if it can be done.
1177
            file_ids_from=None, pull_debian=True):
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1178
        """Import a source package.
1179
1180
        :param dsc_filename: a path to a .dsc file for the version
1181
            to be imported.
327.5.1 by James Westby
Tweaks for auto import.
1182
        :param use_time_from_changelog: whether to use the current time or
1183
            the one from the last changelog entry.
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1184
        """
1185
        base_path = osutils.dirname(dsc_filename)
1186
        dsc = deb822.Dsc(open(dsc_filename).read())
1187
        version = Version(dsc['Version'])
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1188
        format = dsc.get('Format', FORMAT_1_0).strip()
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1189
        extractor_cls = SOURCE_EXTRACTORS.get(format)
1190
        if extractor_cls is None:
1191
            raise AssertionError("Don't know how to import source format %s yet"
1192
                    % format)
1193
        extractor = extractor_cls(dsc_filename, dsc)
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1194
        try:
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1195
            extractor.extract()
1196
            cl = self.get_changelog_from_source(extractor.extracted_debianised)
327.5.1 by James Westby
Tweaks for auto import.
1197
            timestamp = None
1198
            author = None
1199
            if use_time_from_changelog and len(cl._blocks) > 0:
1200
                 raw_timestamp = cl.date
1201
                 import rfc822, time
1202
                 time_tuple = rfc822.parsedate_tz(raw_timestamp)
1203
                 if time_tuple is not None:
747 by Andrew Starr-Bochicchio
import_dsc.py: Use calendar.timegm instead of time.mktime when importing
1204
                     timestamp = (calendar.timegm(
1205
                                  time_tuple[:9]) - time_tuple[9],
1206
                                  time_tuple[9])
423.2.1 by John Arbash Meinel
Fix bug #508251, fall back to iso-8859-1 for author info if utf-8 fails.
1207
                 author = safe_decode(cl.author)
266.1.16 by James Westby
Handle invalid version numbers in the changelog by ignoring them.
1208
            versions = self._get_safe_versions_from_changelog(cl)
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1209
            assert not self.has_version(version), \
1210
                "Trying to import version %s again" % str(version)
1211
            #TODO: check that the versions list is correctly ordered,
1212
            # as some methods assume that, and it's not clear what
1213
            # should happen if it isn't.
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1214
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1215
            if extractor.extracted_upstream is not None:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1216
                self._import_normal_package(dsc['Source'], version, versions,
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1217
                        extractor.extracted_debianised,
1218
                        extractor.unextracted_debian_md5,
1219
                        extractor.extracted_upstream,
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1220
                        extractor.upstream_tarballs,
393.2.1 by James Westby
Add a way to pass trees to take file ids from without them being used as parents.
1221
                        timestamp=timestamp, author=author,
405.1.5 by James Westby
Add a way to prevent pulling even if it can be done.
1222
                        file_ids_from=file_ids_from,
1223
                        pull_debian=pull_debian)
234 by James Westby
Support basic importing of native packages.
1224
            else:
570.2.8 by Jelmer Vernooij
Add package argument to various upstream-related functions.
1225
                self._import_native_package(dsc['Source'], version, versions,
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1226
                        extractor.extracted_debianised,
1227
                        extractor.unextracted_debian_md5,
405.1.5 by James Westby
Add a way to prevent pulling even if it can be done.
1228
                        timestamp=timestamp, file_ids_from=file_ids_from,
1229
                        pull_debian=pull_debian)
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1230
        finally:
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1231
            extractor.cleanup()
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1232
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1233
    def extract_upstream_tree(self, upstream_tips, basedir):
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
1234
        """Extract upstream_tip to a tempdir as a working tree."""
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1235
        # TODO: should stack rather than trying to use the repository,
1236
        # as that will be more efficient.
321.1.3 by James Westby
Drop the requirement for DistributionBranch to have a name.
1237
        to_location = os.path.join(basedir, "upstream")
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
1238
        # Use upstream_branch if it has been set, otherwise self.branch.
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1239
        source_branch = self.pristine_upstream_branch or self.branch
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1240
        assert upstream_tips.keys() == [None]
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1241
        dir_to = source_branch.controldir.sprout(to_location,
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1242
                revision_id=upstream_tips[None],
266.1.14 by James Westby
Fix locking problems with merge_upstream in shared repository.
1243
                accelerator_tree=self.tree)
379.2.4 by Robert Collins
Support merge-upstream in treeless repositories.
1244
        try:
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1245
            self.pristine_upstream_tree = dir_to.open_workingtree()
379.2.4 by Robert Collins
Support merge-upstream in treeless repositories.
1246
        except NoWorkingTree:
1247
            # Handle shared treeless repo's.
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1248
            self.pristine_upstream_tree = dir_to.create_workingtree()
1249
        self.pristine_upstream_branch = self.pristine_upstream_tree.branch
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1250
256 by James Westby
Make merge-upstream in an empty branch work.
1251
    def _create_empty_upstream_tree(self, basedir):
321.1.3 by James Westby
Drop the requirement for DistributionBranch to have a name.
1252
        to_location = os.path.join(basedir, "upstream")
330 by James Westby
Throw out old, unused, merge_upstream and import_dsc code.
1253
        to_transport = get_transport(to_location)
256 by James Westby
Make merge-upstream in an empty branch work.
1254
        to_transport.ensure_base()
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1255
        format = controldir.format_registry.make_controldir('default')
256 by James Westby
Make merge-upstream in an empty branch work.
1256
        try:
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1257
            existing_controldir = controldir.ControlDir.open_from_transport(
256 by James Westby
Make merge-upstream in an empty branch work.
1258
                    to_transport)
1259
        except NotBranchError:
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1260
            # really a NotControlDirError error...
1261
            create_branch = controldir.ControlDir.create_branch_convenience
256 by James Westby
Make merge-upstream in an empty branch work.
1262
            branch = create_branch(to_transport.base,
1263
                    format=format,
1264
                    possible_transports=[to_transport])
1265
        else:
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1266
            if existing_controldir.has_branch():
327.2.3 by James Westby
Clean up from pyflakes
1267
                raise AlreadyBranchError(to_location)
256 by James Westby
Make merge-upstream in an empty branch work.
1268
            else:
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1269
                branch = existing_controldir.create_branch()
1270
                existing_controldir.create_workingtree()
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1271
        self.pristine_upstream_branch = branch
756 by Jelmer Vernooij
Update for breezy, drop support for older versions of bazaar and for debian_bundle.
1272
        self.pristine_upstream_tree = branch.controldir.open_workingtree()
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
1273
        if self.tree:
1274
            root_id = self.tree.path2id('')
1275
        else:
578.2.23 by Jelmer Vernooij
Start determinining parent ids per component.
1276
            tip = self.branch.basis_tree()
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
1277
            with tip.lock_read():
447.1.1 by Robert Collins
Add import-upstream command which imports an upstream - useful for
1278
                root_id = tip.path2id('')
1279
        if root_id:
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1280
            self.pristine_upstream_tree.set_root_id(root_id)
256 by James Westby
Make merge-upstream in an empty branch work.
1281
570.2.5 by Jelmer Vernooij
Pass tarballs along further.
1282
    def _extract_tarballs_to_tempdir(self, tarballs):
1283
        tempdir = tempfile.mkdtemp()
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1284
        try:
570.2.17 by Jelmer Vernooij
Pass along component with tarballs.
1285
            extract_orig_tarballs(
1286
                [(fn, component) for (fn, component, md5) in tarballs],
1287
                tempdir, strip_components=1)
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1288
            return tempdir
1289
        except:
1290
            shutil.rmtree(tempdir)
1291
            raise
1292
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1293
    def _export_previous_upstream_tree(self, package, previous_version, tempdir):
474 by James Westby
Don't strip -n from the version we get in merge-upstream.
1294
        assert isinstance(previous_version, str), \
1295
            "Should pass upstream version as str, not Version."
578.2.8 by Jelmer Vernooij
Avoid unnecessary has_version call.
1296
        try:
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1297
            upstream_tips = self.pristine_upstream_source.version_as_revisions(
494.3.8 by Jelmer Vernooij
Move more functionality onto UpstreamSource classes.
1298
                    package, previous_version)
578.2.8 by Jelmer Vernooij
Avoid unnecessary has_version call.
1299
        except PackageVersionNotPresent:
438.1.1 by Jelmer Vernooij
extract _export_previous_upstream_tree
1300
            raise BzrCommandError("Unable to find the tag for the "
1301
                    "previous upstream version, %s, in the branch: "
1302
                    "%s" % (
474 by James Westby
Don't strip -n from the version we get in merge-upstream.
1303
                previous_version,
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1304
                self.pristine_upstream_source.tag_name(previous_version)))
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1305
        self.extract_upstream_tree(upstream_tips, tempdir)
438.1.1 by Jelmer Vernooij
extract _export_previous_upstream_tree
1306
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1307
    def has_merged_upstream_revisions(self, this_revision, upstream_repository, upstream_revisions):
613.5.5 by Jelmer Vernooij
More refactoring.
1308
        graph = self.branch.repository.get_graph(
1309
            other_repository=upstream_repository)
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1310
        return all(graph.is_ancestor(upstream_revision, this_revision)
1311
                for upstream_revision in upstream_revisions.values())
613.5.5 by Jelmer Vernooij
More refactoring.
1312
570.2.5 by Jelmer Vernooij
Pass tarballs along further.
1313
    def merge_upstream(self, tarball_filenames, package, version, previous_version,
613.5.5 by Jelmer Vernooij
More refactoring.
1314
            upstream_branch=None, upstream_revisions=None, merge_type=None,
402 by James Westby
Add --force to merge-upstream to override UpstreamBranchAlreadyMerged
1315
            force=False):
474 by James Westby
Don't strip -n from the version we get in merge-upstream.
1316
        assert isinstance(version, str), \
475 by James Westby
Refactor cmd_merge_upstream in to smaller chunks.
1317
            "Should pass version as str not %s" % str(type(version))
485.1.1 by Alexandros Frantzis
Accept None as a valid previous_version value in merge_upstream() (LP: #659585)
1318
        assert isinstance(previous_version, str) or previous_version is None, \
475 by James Westby
Refactor cmd_merge_upstream in to smaller chunks.
1319
            "Should pass previous_version as str not %s" % str(
1320
                    type(previous_version))
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1321
        tempdir = tempfile.mkdtemp(dir=os.path.join(self.tree.basedir, '..'))
1322
        try:
256 by James Westby
Make merge-upstream in an empty branch work.
1323
            if previous_version is not None:
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1324
                self._export_previous_upstream_tree(package, previous_version, tempdir)
256 by James Westby
Make merge-upstream in an empty branch work.
1325
            else:
1326
                self._create_empty_upstream_tree(tempdir)
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1327
            if self.pristine_upstream_source.has_version(package, version):
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1328
                raise UpstreamAlreadyImported(version)
472 by James Westby
Avoid an error on merge-upstream with an unrelated branch. Thanks Andrew.
1329
            if upstream_branch is not None:
1330
                upstream_branch.lock_read()
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1331
            try:
474 by James Westby
Don't strip -n from the version we get in merge-upstream.
1332
                if upstream_branch is not None:
613.5.5 by Jelmer Vernooij
More refactoring.
1333
                    if upstream_revisions is None:
1334
                        upstream_revisions = { None: upstream_branch.last_revision() }
1335
                    if (not force and
613.5.6 by Jelmer Vernooij
Use version_as_revisions.
1336
                        self.has_merged_upstream_revisions(self.branch.last_revision(), upstream_branch.repository, upstream_revisions)):
474 by James Westby
Don't strip -n from the version we get in merge-upstream.
1337
                        raise UpstreamBranchAlreadyMerged
570.2.5 by Jelmer Vernooij
Pass tarballs along further.
1338
                upstream_tarballs = [
570.2.17 by Jelmer Vernooij
Pass along component with tarballs.
1339
                    (os.path.abspath(fn), component, md5sum_filename(fn)) for
1340
                    (fn, component) in
570.2.5 by Jelmer Vernooij
Pass tarballs along further.
1341
                    tarball_filenames]
1342
                tarball_dir = self._extract_tarballs_to_tempdir(upstream_tarballs)
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1343
                try:
1344
                    # FIXME: should use upstream_parents()?
613.5.9 by Jelmer Vernooij
Fix iter_versions.
1345
                    parents = { None: [] }
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1346
                    if self.pristine_upstream_branch.last_revision() != NULL_REVISION:
613.5.9 by Jelmer Vernooij
Fix iter_versions.
1347
                        parents = { None: [self.pristine_upstream_branch.last_revision()] }
643.1.2 by Jelmer Vernooij
Some refactoring.
1348
                    imported_revids = self.import_upstream(tarball_dir,
613.5.8 by Jelmer Vernooij
Some reformatting.
1349
                            package, version, parents,
1350
                            upstream_tarballs=upstream_tarballs,
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1351
                            upstream_branch=upstream_branch,
643.1.2 by Jelmer Vernooij
Some refactoring.
1352
                            upstream_revisions=upstream_revisions)
1353
                    self._fetch_upstream_to_branch(imported_revids)
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1354
                finally:
1355
                    shutil.rmtree(tarball_dir)
1356
                if self.branch.last_revision() != NULL_REVISION:
397.1.2 by Robert Collins
When UnrelatedBranches is thrown force a parent that makes reasonable sense for import-dsc - UnrelatedBranches there just means a criss cross has occured.
1357
                    try:
1358
                        conflicts = self.tree.merge_from_branch(
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1359
                                self.pristine_upstream_branch, merge_type=merge_type)
397.1.2 by Robert Collins
When UnrelatedBranches is thrown force a parent that makes reasonable sense for import-dsc - UnrelatedBranches there just means a criss cross has occured.
1360
                    except UnrelatedBranches:
1361
                        # Bug lp:515367 where the first upstream tarball is
1362
                        # missing a proper history link and a criss-cross merge
1363
                        # then recurses and finds no deeper ancestor.
1364
                        # Use the previous upstream import as the from revision
613.5.9 by Jelmer Vernooij
Fix iter_versions.
1365
                        if len(parents[None]) == 0:
553.2.1 by Jelmer Vernooij
* Use --create when merging a new upstream into a branch that doesn't have a
1366
                            from_revision = NULL_REVISION
1367
                        else:
613.5.9 by Jelmer Vernooij
Fix iter_versions.
1368
                            from_revision = parents[None][0]
397.1.2 by Robert Collins
When UnrelatedBranches is thrown force a parent that makes reasonable sense for import-dsc - UnrelatedBranches there just means a criss cross has occured.
1369
                        conflicts = self.tree.merge_from_branch(
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1370
                                self.pristine_upstream_branch, merge_type=merge_type,
553.2.1 by Jelmer Vernooij
* Use --create when merging a new upstream into a branch that doesn't have a
1371
                                from_revision=from_revision)
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1372
                else:
1373
                    # Pull so that merge-upstream allows you to start a branch
1374
                    # from upstream tarball.
1375
                    conflicts = 0
570.1.1 by Jelmer Vernooij
Clarify the meaning of upstream_branch in DistributionBranch().
1376
                    self.tree.pull(self.pristine_upstream_branch)
1377
                self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1378
                return conflicts
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1379
            finally:
321.1.10 by James Westby
Make merge-upstream work with tarball and upstream branch.
1380
                if upstream_branch is not None:
1381
                    upstream_branch.unlock()
254 by James Westby
Switch to DistributionBranch for merge-upstream.
1382
        finally:
1383
            shutil.rmtree(tempdir)
321.1.2 by James Westby
Initial support for pristine-tar.
1384
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1385
1386
class SourceExtractor(object):
1387
    """A class to extract a source package to its constituent parts"""
1388
1389
    def __init__(self, dsc_path, dsc):
1390
        self.dsc_path = dsc_path
1391
        self.dsc = dsc
1392
        self.extracted_upstream = None
1393
        self.extracted_debianised = None
1394
        self.unextracted_debian_md5 = None
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1395
        self.upstream_tarballs = []
1396
        self.tempdir = None
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1397
1398
    def extract(self):
1399
        """Extract the package to a new temporary directory."""
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
1400
        raise NotImplementedError(self.extract)
1401
1402
    def cleanup(self):
1403
        """Cleanup any extracted files."""
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1404
        if self.tempdir is not None and os.path.isdir(self.tempdir):
1405
            shutil.rmtree(self.tempdir)
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
1406
1407
1408
class OneZeroSourceExtractor(SourceExtractor):
1409
    """Source extract for the "1.0" source format."""
1410
1411
    def extract(self):
1412
        """Extract the package to a new temporary directory."""
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1413
        self.tempdir = tempfile.mkdtemp()
1414
        dsc_filename = os.path.abspath(self.dsc_path)
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1415
        proc = subprocess.Popen("dpkg-source -su -x %s" % (dsc_filename,), shell=True,
1416
                cwd=self.tempdir, stdout=subprocess.PIPE,
1417
                stderr=subprocess.STDOUT, preexec_fn=subprocess_setup)
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1418
        (stdout, _) = proc.communicate()
1419
        assert proc.returncode == 0, "dpkg-source -x failed, output:\n%s" % \
1420
                    (stdout,)
1421
        name = self.dsc['Source']
1422
        version = Version(self.dsc['Version'])
1423
        self.extracted_upstream = os.path.join(self.tempdir,
1424
                "%s-%s.orig" % (name, str(version.upstream_version)))
1425
        self.extracted_debianised = os.path.join(self.tempdir,
1426
                "%s-%s" % (name, str(version.upstream_version)))
1427
        if not os.path.exists(self.extracted_upstream):
1428
            mutter("It's a native package")
1429
            self.extracted_upstream = None
1430
        for part in self.dsc['files']:
1431
            if self.extracted_upstream is None:
1432
                if part['name'].endswith(".tar.gz"):
1433
                    self.unextracted_debian_md5 = part['md5sum']
1434
            else:
1435
                if part['name'].endswith(".orig.tar.gz"):
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1436
                    self.upstream_tarballs.append((os.path.abspath(
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1437
                            os.path.join(osutils.dirname(self.dsc_path),
570.2.17 by Jelmer Vernooij
Pass along component with tarballs.
1438
                                part['name'])),
1439
                            component_from_orig_tarball(part['name'], name, str(version.upstream_version)),
1440
                            part['md5sum']))
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1441
                elif part['name'].endswith(".diff.gz"):
1442
                    self.unextracted_debian_md5 = part['md5sum']
1443
1444
1445
class ThreeDotZeroNativeSourceExtractor(SourceExtractor):
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
1446
    """Source extractor for the "3.0 (native)" source format."""
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1447
1448
    def extract(self):
1449
        self.tempdir = tempfile.mkdtemp()
1450
        dsc_filename = os.path.abspath(self.dsc_path)
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1451
        proc = subprocess.Popen("dpkg-source -x %s" % (dsc_filename,), shell=True,
1452
                cwd=self.tempdir, stdout=subprocess.PIPE,
1453
                stderr=subprocess.STDOUT, preexec_fn=subprocess_setup)
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1454
        (stdout, _) = proc.communicate()
1455
        assert proc.returncode == 0, "dpkg-source -x failed, output:\n%s" % \
1456
                    (stdout,)
1457
        name = self.dsc['Source']
1458
        version = Version(self.dsc['Version'])
1459
        self.extracted_debianised = os.path.join(self.tempdir,
1460
                "%s-%s" % (name, str(version.upstream_version)))
1461
        self.extracted_upstream = None
1462
        for part in self.dsc['files']:
409 by James Westby
Handle .bz2 in native packages too.
1463
            if (part['name'].endswith(".tar.gz")
577.2.1 by Jelmer Vernooij
Support lzma in a couple more places.
1464
                    or part['name'].endswith(".tar.bz2")
612.1.1 by Jelmer Vernooij
.tar.lzma -> .tar.xz
1465
                    or part['name'].endswith(".tar.xz")):
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1466
                self.unextracted_debian_md5 = part['md5sum']
1467
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1468
1469
class ThreeDotZeroQuiltSourceExtractor(SourceExtractor):
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
1470
    """Source extractor for the "3.0 (quilt)" source format."""
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1471
1472
    def extract(self):
1473
        self.tempdir = tempfile.mkdtemp()
1474
        dsc_filename = os.path.abspath(self.dsc_path)
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1475
        proc = subprocess.Popen("dpkg-source --skip-debianization -x %s"
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1476
                % (dsc_filename,), shell=True,
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1477
                cwd=self.tempdir, stdout=subprocess.PIPE,
1478
                stderr=subprocess.STDOUT, preexec_fn=subprocess_setup)
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1479
        (stdout, _) = proc.communicate()
1480
        assert proc.returncode == 0, "dpkg-source -x failed, output:\n%s" % \
1481
                    (stdout,)
1482
        name = self.dsc['Source']
1483
        version = Version(self.dsc['Version'])
1484
        self.extracted_debianised = os.path.join(self.tempdir,
1485
                "%s-%s" % (name, str(version.upstream_version)))
1486
        self.extracted_upstream = self.extracted_debianised + ".orig"
1487
        os.rename(self.extracted_debianised, self.extracted_upstream)
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1488
        proc = subprocess.Popen("dpkg-source -x %s" % (dsc_filename,), shell=True,
1489
                cwd=self.tempdir, stdout=subprocess.PIPE,
1490
                stderr=subprocess.STDOUT, preexec_fn=subprocess_setup)
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1491
        (stdout, _) = proc.communicate()
1492
        assert proc.returncode == 0, "dpkg-source -x failed, output:\n%s" % \
1493
                    (stdout,)
429 by James Westby
Chmod unreadable files to workaround http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=558485
1494
        # Check that there are no unreadable files extracted.
1495
        subprocess.call(["find", self.extracted_upstream, "-perm",
1496
                "0000", "-exec", "chmod", "644", "{}", ";"])
1497
        subprocess.call(["find", self.extracted_debianised, "-perm",
1498
                "0000", "-exec", "chmod", "644", "{}", ";"])
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1499
        for part in self.dsc['files']:
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1500
            if part['name'].startswith("%s_%s.orig" % (name, str(version.upstream_version))):
591.2.1 by Jelmer Vernooij
Fix importing of upstream tarballs in import-dsc from 3.0 quilt packages.
1501
                self.upstream_tarballs.append((
1502
                    os.path.abspath(os.path.join(osutils.dirname(self.dsc_path),
1503
                                    part['name'])),
1504
                    component_from_orig_tarball(part['name'], name,
1505
                        str(version.upstream_version)),
1506
                    part['md5sum']))
405.1.2 by James Westby
Support for importing bz2 tarballs.
1507
            elif (part['name'].endswith(".debian.tar.gz")
577.2.1 by Jelmer Vernooij
Support lzma in a couple more places.
1508
                    or part['name'].endswith(".debian.tar.bz2")
612.1.1 by Jelmer Vernooij
.tar.lzma -> .tar.xz
1509
                    or part['name'].endswith(".debian.tar.xz")):
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1510
                self.unextracted_debian_md5 = part['md5sum']
570.2.3 by Jelmer Vernooij
Pass multiple upstream tarballs to _do_import_package.
1511
        assert self.upstream_tarballs is not None, \
612.1.1 by Jelmer Vernooij
.tar.lzma -> .tar.xz
1512
            "Can't handle non gz|bz2|xz tarballs yet"
393.3.4 by James Westby
Be a little more explicit in refusing non gz tarballs.
1513
        assert self.unextracted_debian_md5 is not None, \
612.1.1 by Jelmer Vernooij
.tar.lzma -> .tar.xz
1514
            "Can't handle non gz|bz2|xz tarballs yet"
393.3.2 by James Westby
Implement extracting v3 source formats that aren't very different to v1.
1515
393.3.1 by James Westby
Refactor so that 3.0 support can be implemented with polymorphism.
1516
1517
SOURCE_EXTRACTORS = {}
570.2.1 by Jelmer Vernooij
Split out SourceExtractor base class.
1518
SOURCE_EXTRACTORS[FORMAT_1_0] = OneZeroSourceExtractor
506.1.5 by Jelmer Vernooij
Add constant for format strings.
1519
SOURCE_EXTRACTORS[FORMAT_3_0_NATIVE] = ThreeDotZeroNativeSourceExtractor
1520
SOURCE_EXTRACTORS[FORMAT_3_0_QUILT] = ThreeDotZeroQuiltSourceExtractor