~spiv/bzr-builddeb/trunk-merge-of-use-dpkg-mergechangelogs

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