~barry/bzr-builddeb/609186-urls

126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
1
#    test_import_dsc.py -- Test importing .dsc files.
2
#    Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
260 by James Westby
Copyright updates
3
#              (C) 2008 Canonical Ltd.
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
4
#    
5
#    This file is part of bzr-builddeb.
6
#
7
#    bzr-builddeb is free software; you can redistribute it and/or modify
8
#    it under the terms of the GNU General Public License as published by
9
#    the Free Software Foundation; either version 2 of the License, or
10
#    (at your option) any later version.
11
#
12
#    bzr-builddeb is distributed in the hope that it will be useful,
13
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
#    GNU General Public License for more details.
16
#
17
#    You should have received a copy of the GNU General Public License
18
#    along with bzr-builddeb; if not, write to the Free Software
19
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
#
21
203 by James Westby
Also exclude RCS ,v files when importing.
22
import gzip
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
23
import os
231 by James Westby
Use dpkg-source to build the source packages for testing.
24
import select
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
25
import shutil
231 by James Westby
Use dpkg-source to build the source packages for testing.
26
import subprocess
219 by James Westby
Make running the tests during the build much more robust.
27
import sys
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
28
import tarfile
29
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
30
from debian_bundle.changelog import Version, Changelog
31
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
32
from bzrlib.config import ConfigObj
178.1.29 by James Westby
Add support for incremental import dsc.
33
from bzrlib.conflicts import TextConflict
241 by James Westby
Add an XFAIL test for importing parallel branches.
34
from bzrlib.errors import FileExists, UncommittedChanges, DivergedBranches
35
from bzrlib.tests import TestCaseWithTransport, KnownFailure
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
36
from bzrlib.workingtree import WorkingTree
37
212.1.1 by James Westby
* Don't use relative imports. (LP: #189429)
38
from bzrlib.plugins.builddeb.errors import ImportError, OnlyImportSingleDsc
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
39
from bzrlib.plugins.builddeb.import_dsc import (
40
        DscImporter,
41
        files_to_ignore,
42
        DistributionBranch,
43
        DistributionBranchSet,
44
        )
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
45
46
def write_to_file(filename, contents):
47
  f = open(filename, 'wb')
48
  try:
49
    f.write(contents)
50
  finally:
51
    f.close()
52
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
53
def append_to_file(filename, contents):
54
  f = open(filename, 'ab')
55
  try:
56
    f.write(contents)
57
  finally:
58
    f.close()
59
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
60
class TestDscImporter(TestCaseWithTransport):
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
61
62
  basedir = 'package'
63
  target = 'target'
64
  orig_1 = 'package_0.1.orig.tar.gz'
129 by James Westby
Support importing the second set of .dsc.
65
  orig_2 = 'package_0.2.orig.tar.gz'
178.1.29 by James Westby
Add support for incremental import dsc.
66
  orig_3 = 'package_0.3.orig.tar.gz'
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
67
  diff_1 = 'package_0.1-1.diff.gz'
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
68
  diff_1b = 'package_0.1-2.diff.gz'
129 by James Westby
Support importing the second set of .dsc.
69
  diff_1c = 'package_0.1-3.diff.gz'
70
  diff_2 = 'package_0.2-1.diff.gz'
178.1.29 by James Westby
Add support for incremental import dsc.
71
  diff_3 = 'package_0.3-1.diff.gz'
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
72
  dsc_1 = 'package_0.1-1.dsc'
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
73
  dsc_1b = 'package_0.1-2.dsc'
129 by James Westby
Support importing the second set of .dsc.
74
  dsc_1c = 'package_0.1-3.dsc'
75
  dsc_2 = 'package_0.2-1.dsc'
178.1.29 by James Westby
Add support for incremental import dsc.
76
  dsc_3 = 'package_0.3-1.dsc'
135 by James Westby
Initial support for importing native packages.
77
  native_1 = 'package_0.1.tar.gz'
78
  native_2 = 'package_0.2.tar.gz'
79
  native_dsc_1 = 'package_0.1.dsc'
80
  native_dsc_2 = 'package_0.2.dsc'
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
81
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
82
  config_files = ['.bzr-builddeb/', '.bzr-builddeb/default.conf']
83
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
84
  def assertRulesExecutable(self, tree):
85
    """Checks that the debian/rules in the tree is executable"""
195 by James Westby
* Fix the import diff code to not deadlock on large diffs. Thanks to
86
    tree.lock_read()
87
    try:
88
      self.assertTrue(tree.is_executable(tree.path2id('debian/rules')))
89
    finally:
90
      tree.unlock()
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
91
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
92
  def make_base_package(self):
93
    os.mkdir(self.basedir)
94
    write_to_file(os.path.join(self.basedir, 'README'), 'hello\n')
95
    write_to_file(os.path.join(self.basedir, 'CHANGELOG'), 'version 1\n')
96
    write_to_file(os.path.join(self.basedir, 'Makefile'), 'bad command\n')
198 by James Westby
* Exclude more files/directories than just .bzr when importing.
97
    for filename in files_to_ignore:
98
      write_to_file(os.path.join(self.basedir, filename),
99
          "you ain't seen me, right?")
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
100
129 by James Westby
Support importing the second set of .dsc.
101
  def extend_base_package(self):
102
    write_to_file(os.path.join(self.basedir, 'NEWS'), 'new release\n')
103
    write_to_file(os.path.join(self.basedir, 'Makefile'), 'good command\n')
136 by James Westby
Add tests for non-native -> native transition on import.
104
    write_to_file(os.path.join(self.basedir, 'from_debian'), 'from debian\n')
198 by James Westby
* Exclude more files/directories than just .bzr when importing.
105
    for filename in files_to_ignore:
106
      os.unlink(os.path.join(self.basedir, filename))
129 by James Westby
Support importing the second set of .dsc.
107
178.1.29 by James Westby
Add support for incremental import dsc.
108
  def extend_base_package2(self):
109
    write_to_file(os.path.join(self.basedir, 'NEW_IN_3'), 'new release\n')
110
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
111
  def make_orig_1(self):
112
    self.make_base_package()
113
    tar = tarfile.open(self.orig_1, 'w:gz')
114
    try:
115
      tar.add(self.basedir)
116
    finally:
117
      tar.close()
118
129 by James Westby
Support importing the second set of .dsc.
119
  def make_orig_2(self):
120
    self.extend_base_package()
121
    tar = tarfile.open(self.orig_2, 'w:gz')
122
    try:
123
      tar.add(self.basedir)
124
    finally:
125
      tar.close()
126
178.1.29 by James Westby
Add support for incremental import dsc.
127
  def make_orig_3(self):
128
    self.extend_base_package2()
129
    tar = tarfile.open(self.orig_3, 'w:gz')
130
    try:
131
      tar.add(self.basedir)
132
    finally:
133
      tar.close()
134
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
135
  def make_diff_1(self):
136
    diffdir = 'package-0.1'
137
    shutil.copytree(self.basedir, diffdir)
138
    os.mkdir(os.path.join(diffdir, 'debian'))
139
    write_to_file(os.path.join(diffdir, 'debian', 'changelog'),
140
                  'version 1-1\n')
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
141
    write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
142
    write_to_file(os.path.join(diffdir, 'Makefile'), 'good command\n')
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
143
    write_to_file(os.path.join(diffdir, 'debian', 'rules'), '\n')
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
144
    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
145
                                                   self.diff_1))
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
146
147
  def make_diff_1b(self):
148
    diffdir = 'package-0.1'
149
    append_to_file(os.path.join(diffdir, 'debian', 'changelog'),
150
                   'version 1-2\n')
151
    write_to_file(os.path.join(diffdir, 'debian', 'control'), 'package\n')
152
    os.unlink(os.path.join(diffdir, 'debian', 'install'))
153
    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
154
                                                   self.diff_1b))
155
129 by James Westby
Support importing the second set of .dsc.
156
  def make_diff_1c(self):
157
    diffdir = 'package-0.1'
158
    append_to_file(os.path.join(diffdir, 'debian', 'changelog'),
159
                   'version 1-3\n')
160
    write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
136 by James Westby
Add tests for non-native -> native transition on import.
161
    write_to_file(os.path.join(diffdir, 'from_debian'), 'from debian\n')
129 by James Westby
Support importing the second set of .dsc.
162
    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
163
                                                   self.diff_1c))
164
165
  def make_diff_2(self):
166
    diffdir = 'package-0.2'
167
    shutil.copytree(self.basedir, diffdir)
168
    os.mkdir(os.path.join(diffdir, 'debian'))
169
    write_to_file(os.path.join(diffdir, 'debian', 'changelog'),
170
                  'version 1-1\nversion 1-2\nversion 1-3\nversion 2-1\n')
171
    write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
172
    write_to_file(os.path.join(diffdir, 'debian', 'rules'), '\n')
198 by James Westby
* Exclude more files/directories than just .bzr when importing.
173
    for filename in files_to_ignore:
174
      write_to_file(os.path.join(diffdir, filename),
175
          "i'm like some annoying puppy")
129 by James Westby
Support importing the second set of .dsc.
176
    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
177
                                                   self.diff_2))
178
178.1.29 by James Westby
Add support for incremental import dsc.
179
  def make_diff_3(self):
180
    diffdir = 'package-0.3'
181
    shutil.copytree(self.basedir, diffdir)
178.1.35 by James Westby
* Filter out any changes to .bzr in packages that are being imported as they
182
    os.mkdir(os.path.join(diffdir, '.bzr'))
183
    write_to_file(os.path.join(diffdir, '.bzr', 'branch-format'),
184
        'broken format')
178.1.29 by James Westby
Add support for incremental import dsc.
185
    os.mkdir(os.path.join(diffdir, 'debian'))
186
    write_to_file(os.path.join(diffdir, 'debian', 'changelog'),
187
          'version 1-1\nversion 1-2\nversion 1-3\nversion 2-1\nversion 3-1\n')
188
    write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
189
    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
190
                                                   self.diff_3))
191
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
192
  def make_dsc(self, filename, version, file1, extra_files=[],
193
               package='package'):
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
194
    write_to_file(filename, """Format: 1.0
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
195
Source: %s
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
196
Version: %s
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
197
Binary: package
198
Maintainer: maintainer <maint@maint.org>
199
Architecture: any
200
Standards-Version: 3.7.2
201
Build-Depends: debhelper (>= 5.0.0)
202
Files:
203
 8636a3e8ae81664bac70158503aaf53a 1328218 %s
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
204
""" % (package, version, os.path.basename(file1)))
130 by James Westby
Improve the handling of strange .dsc files.
205
    i = 1
206
    for extra_file in extra_files:
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
207
      append_to_file(filename,
130 by James Westby
Improve the handling of strange .dsc files.
208
                     " 1acd97ad70445afd5f2a64858296f21%d 20709 %s\n" % \
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
209
                     (i, os.path.basename(extra_file)))
130 by James Westby
Improve the handling of strange .dsc files.
210
      i += 1
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
211
212
  def make_dsc_1(self):
213
    self.make_orig_1()
214
    self.make_diff_1()
130 by James Westby
Improve the handling of strange .dsc files.
215
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, [self.diff_1])
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
216
217
  def make_dsc_1b(self):
218
    self.make_diff_1b()
219
    self.make_dsc(self.dsc_1b, '0.1-2', self.diff_1b)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
220
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
221
  def make_dsc_1b_repeated_orig(self):
222
    self.make_diff_1b()
223
    self.make_dsc(self.dsc_1b, '0.1-2', self.orig_1, [self.diff_1b])
224
129 by James Westby
Support importing the second set of .dsc.
225
  def make_dsc_1c(self):
226
    self.make_diff_1c()
227
    self.make_dsc(self.dsc_1c, '0.1-3', self.diff_1c)
228
229
  def make_dsc_2(self):
230
    self.make_orig_2()
231
    self.make_diff_2()
130 by James Westby
Improve the handling of strange .dsc files.
232
    self.make_dsc(self.dsc_2, '0.2-1', self.orig_2, [self.diff_2])
129 by James Westby
Support importing the second set of .dsc.
233
178.1.29 by James Westby
Add support for incremental import dsc.
234
  def make_dsc_3(self):
235
    self.make_orig_3()
236
    self.make_diff_3()
237
    self.make_dsc(self.dsc_3, '0.3-1', self.orig_3, [self.diff_3])
238
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
239
  def import_dsc_1(self):
240
    self.make_dsc_1()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
241
    DscImporter([self.dsc_1]).import_dsc(self.target)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
242
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
243
  def import_dsc_1b(self):
244
    self.make_dsc_1()
245
    self.make_dsc_1b()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
246
    DscImporter([self.dsc_1, self.dsc_1b]).import_dsc(self.target)
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
247
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
248
  def import_dsc_1b_repeated_diff(self):
249
    self.make_dsc_1()
250
    self.make_dsc_1b()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
251
    DscImporter([self.dsc_1, self.dsc_1b, self.dsc_1b]).import_dsc(self.target)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
252
129 by James Westby
Support importing the second set of .dsc.
253
  def import_dsc_1c(self):
254
    self.make_dsc_1()
255
    self.make_dsc_1b()
256
    self.make_dsc_1c()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
257
    DscImporter([self.dsc_1, self.dsc_1c, self.dsc_1b]).import_dsc(self.target)
129 by James Westby
Support importing the second set of .dsc.
258
259
  def import_dsc_2(self):
260
    self.make_dsc_1()
261
    self.make_dsc_1b()
262
    self.make_dsc_1c()
263
    self.make_dsc_2()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
264
    importer = DscImporter([self.dsc_1, self.dsc_1b, self.dsc_1c, self.dsc_2])
265
    importer.import_dsc(self.target)
129 by James Westby
Support importing the second set of .dsc.
266
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
267
  def import_dsc_2_repeated_orig(self):
268
    self.make_dsc_1()
269
    self.make_dsc_1b_repeated_orig()
270
    self.make_dsc_1c()
271
    self.make_dsc_2()
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
272
    importer = DscImporter([self.dsc_1, self.dsc_1b, self.dsc_1c, self.dsc_2])
273
    importer.import_dsc(self.target)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
274
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
275
  def test_import_dsc_target_extant(self):
276
    os.mkdir(self.target)
277
    write_to_file('package_0.1.dsc', '')
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
278
    importer = DscImporter([self.dsc_1])
279
    self.assertRaises(FileExists, importer.import_dsc, self.target)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
280
281
  def test_import_one_dsc_tree(self):
282
    self.import_dsc_1()
283
    self.failUnlessExists(self.target)
129 by James Westby
Support importing the second set of .dsc.
284
    tree = WorkingTree.open(self.target)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
285
    tree.lock_read()
286
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
287
                    'debian/changelog', 'debian/install', 'debian/rules']
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
288
    try:
289
      self.check_inventory_shape(tree.inventory, expected_inv)
290
    finally:
291
      tree.unlock()
292
    for path in expected_inv:
293
      self.failUnlessExists(os.path.join(self.target, path))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
294
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
295
                           'good command\n')
296
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
297
                           'version 1-1\n')
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
298
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(),
299
                     False)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
300
    self.assertRulesExecutable(tree)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
301
302
  def test_import_one_dsc_history(self):
303
    self.import_dsc_1()
129 by James Westby
Support importing the second set of .dsc.
304
    tree = WorkingTree.open(self.target)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
305
    rh = tree.branch.revision_history()
306
    self.assertEqual(len(rh), 2)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
307
    self.check_revision_message(tree, rh[0],
308
                          'import upstream from %s' % self.orig_1)
309
    self.check_revision_message(tree, rh[1],
310
                          'merge packaging changes from %s' % self.diff_1)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
311
    changes = tree.changes_from(tree.branch.repository.revision_tree(rh[0]))
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
312
    expected_added = ['debian/', 'debian/changelog', 'debian/install',
313
                      'debian/rules']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
314
    expected_modified = ['Makefile']
315
    self.check_changes(changes, added=expected_added,
316
                       modified=expected_modified)
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
317
    tag = tree.branch.tags.lookup_tag('upstream-0.1')
318
    self.assertEqual(tag, rh[0])
319
320
  def test_import_two_dsc_one_upstream_tree(self):
321
    self.import_dsc_1b()
322
    self.failUnlessExists(self.target)
129 by James Westby
Support importing the second set of .dsc.
323
    tree = WorkingTree.open(self.target)
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
324
    tree.lock_read()
325
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
326
                    'debian/changelog', 'debian/control', 'debian/rules']
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
327
    try:
328
      self.check_inventory_shape(tree.inventory, expected_inv)
329
    finally:
330
      tree.unlock()
331
    for path in expected_inv:
332
      self.failUnlessExists(os.path.join(self.target, path))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
333
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
334
                           'good command\n')
335
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
336
                           'version 1-1\nversion 1-2\n')
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
337
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(),
338
                     False)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
339
    self.assertRulesExecutable(tree)
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
340
341
  def test_import_two_dsc_one_upstream_history(self):
342
    self.import_dsc_1b()
129 by James Westby
Support importing the second set of .dsc.
343
    tree = WorkingTree.open(self.target)
127 by James Westby
Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
344
    rh = tree.branch.revision_history()
345
    self.assertEqual(len(rh), 3)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
346
    self.check_revision_message(tree, rh[0],
347
                          'import upstream from %s' % self.orig_1)
348
    self.check_revision_message(tree, rh[1],
349
                          'merge packaging changes from %s' % self.diff_1)
350
    self.check_revision_message(tree, rh[2],
351
                          'merge packaging changes from %s' % self.diff_1b)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
352
    prev_tree = tree.branch.repository.revision_tree(rh[1])
353
    changes = tree.changes_from(prev_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
354
    expected_added = ['debian/control']
355
    expected_removed = ['debian/install']
356
    expected_modified = ['debian/changelog']
357
    self.check_changes(changes, added=expected_added,
358
                       removed=expected_removed, modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
359
    self.assertRulesExecutable(prev_tree)
126 by James Westby
Start work on import_dsc, which creates a branch from a set of source packages.
360
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
361
  def test_import_two_dsc_one_upstream_history_repeated_diff(self):
362
    self.import_dsc_1b_repeated_diff()
363
    tree = WorkingTree.open(self.target)
364
    rh = tree.branch.revision_history()
365
    self.assertEqual(len(rh), 3)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
366
    self.check_revision_message(tree, rh[0],
367
                          'import upstream from %s' % self.orig_1)
368
    self.check_revision_message(tree, rh[1],
369
                          'merge packaging changes from %s' % self.diff_1)
370
    self.check_revision_message(tree, rh[2],
371
                          'merge packaging changes from %s' % self.diff_1b)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
372
    prev_tree = tree.branch.repository.revision_tree(rh[1])
373
    changes = tree.changes_from(prev_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
374
    expected_added = ['debian/control']
375
    expected_removed = ['debian/install']
376
    expected_modified = ['debian/changelog']
377
    self.check_changes(changes, added=expected_added,
378
                       removed=expected_removed, modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
379
    self.assertRulesExecutable(prev_tree)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
380
129 by James Westby
Support importing the second set of .dsc.
381
  def test_import_three_dsc_one_upstream_tree(self):
382
    self.import_dsc_1c()
383
    self.failUnlessExists(self.target)
384
    tree = WorkingTree.open(self.target)
385
    tree.lock_read()
136 by James Westby
Add tests for non-native -> native transition on import.
386
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'from_debian',
387
                    'debian/', 'debian/changelog', 'debian/control',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
388
                    'debian/install', 'debian/rules']
129 by James Westby
Support importing the second set of .dsc.
389
    try:
390
      self.check_inventory_shape(tree.inventory, expected_inv)
391
    finally:
392
      tree.unlock()
393
    for path in expected_inv:
394
      self.failUnlessExists(os.path.join(self.target, path))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
395
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
396
                           'good command\n')
397
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
398
                           'version 1-1\nversion 1-2\nversion 1-3\n')
129 by James Westby
Support importing the second set of .dsc.
399
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(),
400
                     False)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
401
    self.assertRulesExecutable(tree)
129 by James Westby
Support importing the second set of .dsc.
402
403
  def test_import_three_dsc_one_upstream_history(self):
404
    self.import_dsc_1c()
405
    tree = WorkingTree.open(self.target)
406
    rh = tree.branch.revision_history()
407
    self.assertEqual(len(rh), 4)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
408
    self.check_revision_message(tree, rh[0],
409
                          'import upstream from %s' % self.orig_1)
410
    self.check_revision_message(tree, rh[1],
411
                          'merge packaging changes from %s' % self.diff_1)
412
    self.check_revision_message(tree, rh[2],
413
                          'merge packaging changes from %s' % self.diff_1b)
414
    self.check_revision_message(tree, rh[3],
415
                          'merge packaging changes from %s' % self.diff_1c)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
416
    prev_tree = tree.branch.repository.revision_tree(rh[2])
417
    changes = tree.changes_from(prev_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
418
    expected_added = ['debian/install', 'from_debian']
419
    expected_modified = ['debian/changelog']
420
    self.check_changes(changes, added=expected_added,
421
                       modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
422
    self.assertRulesExecutable(prev_tree)
129 by James Westby
Support importing the second set of .dsc.
423
424
  def test_import_three_dsc_two_upstream_tree(self):
425
    self.import_dsc_2()
426
    self.failUnlessExists(self.target)
427
    tree = WorkingTree.open(self.target)
428
    tree.lock_read()
136 by James Westby
Add tests for non-native -> native transition on import.
429
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'from_debian',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
430
                    'debian/', 'debian/changelog', 'debian/install',
431
                    'debian/rules']
129 by James Westby
Support importing the second set of .dsc.
432
    try:
433
      self.check_inventory_shape(tree.inventory, expected_inv)
434
    finally:
435
      tree.unlock()
436
    for path in expected_inv:
437
      self.failUnlessExists(os.path.join(self.target, path))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
438
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
439
                           'good command\n')
440
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
129 by James Westby
Support importing the second set of .dsc.
441
                     'version 1-1\nversion 1-2\nversion 1-3\nversion 2-1\n')
442
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(),
443
                     False)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
444
    self.assertRulesExecutable(tree)
129 by James Westby
Support importing the second set of .dsc.
445
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
446
  def assertContentsAre(self, filename, expected_contents):
447
    f = open(filename)
448
    try:
449
      contents = f.read()
450
    finally:
451
      f.close()
452
    self.assertEqual(contents, expected_contents,
453
                     "Contents of %s are not as expected" % filename)
454
129 by James Westby
Support importing the second set of .dsc.
455
  def test_import_four_dsc_two_upstream_history(self):
456
    self.import_dsc_2()
457
    tree = WorkingTree.open(self.target)
458
    rh = tree.branch.revision_history()
459
    self.assertEqual(len(rh), 3)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
460
    self.check_revision_message(tree, rh[0],
461
                          'import upstream from %s' % self.orig_1)
462
    self.check_revision_message(tree, rh[1],
463
                          'import upstream from %s' % self.orig_2)
464
    self.check_revision_message(tree, rh[2],
465
                         'merge packaging changes from %s' % self.diff_2)
129 by James Westby
Support importing the second set of .dsc.
466
    parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
467
    self.assertEqual(parents, [rh[0]], rh)
468
    parents = tree.branch.repository.revision_tree(rh[2]).get_parent_ids()
469
    self.assertEqual(len(parents), 2)
470
    self.assertEqual(parents[0], rh[1], rh)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
471
    self.check_revision_message(tree, parents[1],
129 by James Westby
Support importing the second set of .dsc.
472
                     'merge packaging changes from %s' % self.diff_1c)
473
    # Check the diff against upstream.
474
    changes = tree.changes_from(tree.branch.repository.revision_tree(rh[1]))
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
475
    expected_added = ['debian/', 'debian/changelog', 'debian/install',
476
                      'debian/rules']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
477
    self.check_changes(changes, added=expected_added)
129 by James Westby
Support importing the second set of .dsc.
478
    # Check the diff against last packaging version
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
479
    last_package_tree = tree.branch.repository.revision_tree(parents[1])
480
    changes = tree.changes_from(last_package_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
481
    expected_added = ['NEWS']
482
    expected_removed = ['debian/control']
483
    expected_modified = ['debian/changelog']
484
    self.check_changes(changes, added=expected_added,
485
                       removed=expected_removed, modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
486
    self.assertRulesExecutable(tree)
487
    self.assertRulesExecutable(last_package_tree)
129 by James Westby
Support importing the second set of .dsc.
488
130 by James Westby
Improve the handling of strange .dsc files.
489
  def test_import_dsc_restrictions_on_dscs(self):
490
    """Test that errors are raised for confusing sets of .dsc files."""
491
    self.make_dsc(self.dsc_1, '0.1-1', self.diff_1)
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
492
    importer = DscImporter([self.dsc_1])
493
    self.assertRaises(ImportError, importer.import_dsc, self.target)
130 by James Westby
Improve the handling of strange .dsc files.
494
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1)
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
495
    importer = DscImporter([self.dsc_1])
496
    self.assertRaises(ImportError, importer.import_dsc, self.target)
130 by James Westby
Improve the handling of strange .dsc files.
497
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, [self.diff_1, self.diff_1])
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
498
    importer = DscImporter([self.dsc_1])
499
    self.assertRaises(ImportError, importer.import_dsc, self.target)
130 by James Westby
Improve the handling of strange .dsc files.
500
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, [self.orig_1, self.diff_1])
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
501
    importer = DscImporter([self.dsc_1])
502
    self.assertRaises(ImportError, importer.import_dsc, self.target)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
503
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, [self.diff_1])
504
    self.make_dsc(self.dsc_1b, '0.1-2', self.diff_1b, package='otherpackage')
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
505
    importer = DscImporter([self.dsc_1, self.dsc_1b])
506
    self.assertRaises(ImportError, importer.import_dsc, self.target)
135 by James Westby
Initial support for importing native packages.
507
    self.make_dsc(self.dsc_1, '0.1', self.diff_1b, [self.orig_1,
508
                                                    self.native_1])
509
    importer = DscImporter([self.dsc_1])
510
    self.assertRaises(ImportError, importer.import_dsc, self.target)
511
    self.make_dsc(self.dsc_1, '0.1', self.native_1, [self.native_1])
512
    importer = DscImporter([self.dsc_1])
513
    self.assertRaises(ImportError, importer.import_dsc, self.target)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
514
515
  def test_import_four_dsc_two_upstream_history_repeated_orig(self):
516
    self.import_dsc_2_repeated_orig()
517
    tree = WorkingTree.open(self.target)
518
    rh = tree.branch.revision_history()
519
    self.assertEqual(len(rh), 3)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
520
    self.check_revision_message(tree, rh[0], 'import upstream from %s' % \
521
                                self.orig_1)
522
    self.check_revision_message(tree, rh[1], 'import upstream from %s' % \
523
                                self.orig_2)
524
    self.check_revision_message(tree, rh[2],
525
                         'merge packaging changes from %s' % self.diff_2)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
526
    parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
527
    self.assertEqual(parents, [rh[0]], rh)
528
    parents = tree.branch.repository.revision_tree(rh[2]).get_parent_ids()
529
    self.assertEqual(len(parents), 2)
530
    self.assertEqual(parents[0], rh[1], rh)
531
    self.assertEqual(tree.branch.repository.get_revision(parents[1]).message,
532
                     'merge packaging changes from %s' % self.diff_1c)
533
    # Check the diff against upstream.
534
    changes = tree.changes_from(tree.branch.repository.revision_tree(rh[1]))
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
535
    expected_added = ['debian/', 'debian/changelog', 'debian/install',
536
                      'debian/rules']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
537
    self.check_changes(changes, added=expected_added)
131 by James Westby
Add an (untested) import-snapshot command that imports from snapshot.d.n.
538
    # Check the diff against last packaging version
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
539
    last_package_tree = tree.branch.repository.revision_tree(parents[1])
540
    changes = tree.changes_from(last_package_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
541
    expected_added = ['NEWS']
542
    expected_removed = ['debian/control']
543
    expected_modified = ['debian/changelog']
544
    self.check_changes(changes, added=expected_added,
545
                       removed=expected_removed, modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
546
    self.assertRulesExecutable(tree)
547
    self.assertRulesExecutable(last_package_tree)
130 by James Westby
Improve the handling of strange .dsc files.
548
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
549
  def test_import_dsc_different_dir(self):
550
    source = 'source'
551
    os.mkdir(source)
552
    self.diff_1 = os.path.join(source, self.diff_1)
553
    self.orig_1 = os.path.join(source, self.orig_1)
554
    self.dsc_1 = os.path.join(source, self.dsc_1)
555
    self.import_dsc_1()
556
    self.failUnlessExists(self.target)
557
    tree = WorkingTree.open(self.target)
558
    tree.lock_read()
559
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
560
                    'debian/changelog', 'debian/install', 'debian/rules']
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
561
    try:
562
      self.check_inventory_shape(tree.inventory, expected_inv)
563
    finally:
564
      tree.unlock()
565
    for path in expected_inv:
566
      self.failUnlessExists(os.path.join(self.target, path))
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
567
    self.assertRulesExecutable(tree)
133 by James Westby
Refactor import_dsc to be a bit cleaner. Still needs some work.
568
178.1.35 by James Westby
* Filter out any changes to .bzr in packages that are being imported as they
569
  def _add_debian_to_native(self):
570
    os.mkdir(os.path.join(self.basedir, 'debian'))
571
    write_to_file(os.path.join(self.basedir, 'debian', 'changelog'),
572
                  'version 1\n')
573
    write_to_file(os.path.join(self.basedir, 'debian', 'rules'), '\n')
574
575
  def _make_native(self, tarball_name, dsc_name):
576
    tar = tarfile.open(tarball_name, 'w:gz')
577
    try:
578
      tar.add(self.basedir)
579
    finally:
580
      tar.close()
581
    self.make_dsc(dsc_name, '0.1', tarball_name)
582
583
135 by James Westby
Initial support for importing native packages.
584
  def make_native_dsc_1(self):
585
    self.make_base_package()
178.1.35 by James Westby
* Filter out any changes to .bzr in packages that are being imported as they
586
    self._add_debian_to_native()
587
    self._make_native(self.native_1, self.native_dsc_1)
135 by James Westby
Initial support for importing native packages.
588
589
  def make_native_dsc_2(self):
590
    self.extend_base_package()
591
    append_to_file(os.path.join(self.basedir, 'debian', 'changelog'),
592
                   'version 2\n')
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
593
    write_to_file(os.path.join(self.basedir, 'debian', 'rules'), '\n')
135 by James Westby
Initial support for importing native packages.
594
    tar = tarfile.open(self.native_2, 'w:gz')
595
    try:
596
      tar.add(self.basedir)
597
    finally:
598
      tar.close()
599
    self.make_dsc(self.native_dsc_2, '0.2', self.native_2)
600
136 by James Westby
Add tests for non-native -> native transition on import.
601
  def make_native_dsc_2_after_non_native(self):
602
    self.extend_base_package()
603
    os.mkdir(os.path.join(self.basedir, 'debian'))
604
    write_to_file(os.path.join(self.basedir, 'debian', 'changelog'),
605
                  'version 1\nversion 2\n')
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
606
    write_to_file(os.path.join(self.basedir, 'debian', 'rules'), '\n')
136 by James Westby
Add tests for non-native -> native transition on import.
607
    tar = tarfile.open(self.native_2, 'w:gz')
608
    try:
609
      tar.add(self.basedir)
610
    finally:
611
      tar.close()
612
    self.make_dsc(self.native_dsc_2, '0.2', self.native_2)
613
135 by James Westby
Initial support for importing native packages.
614
  def test_import_dsc_native_single(self):
615
    self.make_native_dsc_1()
616
    importer = DscImporter([self.native_dsc_1])
617
    importer.import_dsc(self.target)
618
    tree = WorkingTree.open(self.target)
619
    expected_inv = ['CHANGELOG', 'README', 'Makefile', 'debian/',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
620
                    'debian/changelog', 'debian/rules'] + self.config_files
135 by James Westby
Initial support for importing native packages.
621
    tree.lock_read()
622
    try:
623
      self.check_inventory_shape(tree.inventory, expected_inv)
624
    finally:
625
      tree.unlock()
626
    rh = tree.branch.revision_history()
627
    self.assertEqual(len(rh), 1)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
628
    self.check_revision_message(tree, rh[0], "import package from %s" % \
135 by James Westby
Initial support for importing native packages.
629
                     os.path.basename(self.native_1))
630
    self.assertEqual(len(tree.get_parent_ids()), 1)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
631
    self.check_is_native_in_config(tree)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
632
    self.assertRulesExecutable(tree)
135 by James Westby
Initial support for importing native packages.
633
634
  def test_import_dsc_native_double(self):
635
    self.make_native_dsc_1()
636
    self.make_native_dsc_2()
637
    importer = DscImporter([self.native_dsc_1, self.native_dsc_2])
638
    importer.import_dsc(self.target)
639
    tree = WorkingTree.open(self.target)
136 by James Westby
Add tests for non-native -> native transition on import.
640
    expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'from_debian',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
641
                    'debian/', 'debian/changelog', 'debian/rules'] \
642
                   + self.config_files
135 by James Westby
Initial support for importing native packages.
643
    tree.lock_read()
644
    try:
645
      self.check_inventory_shape(tree.inventory, expected_inv)
646
    finally:
647
      tree.unlock()
648
    rh = tree.branch.revision_history()
649
    self.assertEqual(len(rh), 2)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
650
    self.check_revision_message(tree, rh[0], "import package from %s" % \
135 by James Westby
Initial support for importing native packages.
651
                     os.path.basename(self.native_1))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
652
    self.check_revision_message(tree, rh[1], "import package from %s" % \
135 by James Westby
Initial support for importing native packages.
653
                     os.path.basename(self.native_2))
654
    self.assertEqual(len(tree.get_parent_ids()), 1)
655
    parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
656
    self.assertEqual(len(parents), 1)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
657
    self.check_is_native_in_config(tree)
658
    old_tree = tree.branch.repository.revision_tree(rh[0])
659
    self.check_is_native_in_config(old_tree)
660
    changes = tree.changes_from(old_tree)
661
    expected_added = ['NEWS', 'from_debian']
662
    expected_modified = ['Makefile', 'debian/changelog']
663
    self.check_changes(changes, added=expected_added,
664
                       modified=expected_modified)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
665
    self.assertRulesExecutable(tree)
666
    self.assertRulesExecutable(old_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
667
668
  def check_revision_message(self, tree, revision, expected_message):
669
    rev = tree.branch.repository.get_revision(revision)
670
    self.assertEqual(rev.message, expected_message)
135 by James Westby
Initial support for importing native packages.
671
136 by James Westby
Add tests for non-native -> native transition on import.
672
  def test_non_native_to_native(self):
673
    self.make_dsc_1()
674
    self.make_native_dsc_2_after_non_native()
675
    importer = DscImporter([self.dsc_1, self.native_dsc_2])
676
    importer.import_dsc(self.target)
677
    tree = WorkingTree.open(self.target)
678
    expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'from_debian',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
679
                    'debian/', 'debian/changelog', 'debian/rules'] \
680
                   + self.config_files
136 by James Westby
Add tests for non-native -> native transition on import.
681
    tree.lock_read()
682
    try:
683
      self.check_inventory_shape(tree.inventory, expected_inv)
684
    finally:
685
      tree.unlock()
686
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(), False)
687
    rh = tree.branch.revision_history()
688
    self.assertEqual(len(rh), 2)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
689
    self.check_revision_message(tree, rh[0], "import upstream from %s" % \
136 by James Westby
Add tests for non-native -> native transition on import.
690
                     os.path.basename(self.orig_1))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
691
    self.check_revision_message(tree, rh[1], "import package from %s" % \
136 by James Westby
Add tests for non-native -> native transition on import.
692
                     os.path.basename(self.native_2))
693
    self.assertEqual(len(tree.get_parent_ids()), 1)
694
    parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
695
    self.assertEqual(len(parents), 2)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
696
    self.check_revision_message(tree, parents[1],
136 by James Westby
Add tests for non-native -> native transition on import.
697
                     "merge packaging changes from %s" % \
698
                     os.path.basename(self.diff_1))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
699
    up_tree = tree.branch.repository.revision_tree(rh[0])
700
    changes = tree.changes_from(up_tree)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
701
    expected_added = ['NEWS', 'debian/', 'debian/changelog', 'debian/rules',
702
                      'from_debian']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
703
    expected_added += self.config_files
704
    self.check_changes(changes, added=expected_added, modified=['Makefile'])
705
    package_tree = tree.branch.repository.revision_tree(parents[1])
706
    changes = tree.changes_from(package_tree)
707
    expected_added = ['NEWS', 'from_debian'] + self.config_files
708
    expected_modified = ['debian/changelog']
709
    expected_removed = ['debian/install']
710
    self.check_changes(changes, added=expected_added,
711
                       modified=expected_modified, removed=expected_removed)
712
    self.check_is_not_native_in_config(up_tree)
713
    self.check_is_not_native_in_config(package_tree)
714
    self.check_is_native_in_config(tree)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
715
    self.assertRulesExecutable(tree)
716
    self.assertRulesExecutable(package_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
717
718
  def check_changes(self, changes, added=[], removed=[], modified=[],
719
                    renamed=[]):
720
    exp_added = set(added)
721
    exp_removed = set(removed)
722
    exp_modified = set(modified)
723
    exp_renamed = set(renamed)
724
725
    def make_set(list):
726
      output = set()
727
      for item in list:
728
        if item[2] == 'directory':
729
          output.add(item[0] + '/')
730
        else:
731
          output.add(item[0])
732
      return output
733
734
    real_added = make_set(changes.added)
735
    real_removed = make_set(changes.removed)
736
    real_modified = make_set(changes.modified)
737
    real_renamed = make_set(changes.renamed)
738
    missing_added = exp_added.difference(real_added)
739
    missing_removed = exp_removed.difference(real_removed)
740
    missing_modified = exp_modified.difference(real_modified)
741
    missing_renamed = exp_renamed.difference(real_renamed)
742
    extra_added = real_added.difference(exp_added)
743
    extra_removed = real_removed.difference(exp_removed)
744
    extra_modified = real_modified.difference(exp_modified)
745
    extra_renamed = real_renamed.difference(exp_renamed)
746
    if len(missing_added) > 0:
747
      self.fail("Some expected paths not found added in the changes: %s" % \
748
                 str(missing_added))
749
    if len(missing_removed) > 0:
750
      self.fail("Some expected paths not found removed in the changes: %s" % \
751
                 str(missing_removed))
752
    if len(missing_modified) > 0:
753
      self.fail("Some expected paths not found modified in the changes: %s" % \
754
                 str(missing_modified))
755
    if len(missing_renamed) > 0:
756
      self.fail("Some expected paths not found renamed in the changes: %s" % \
757
                 str(missing_renamed))
758
    if len(extra_added) > 0:
759
      self.fail("Some extra paths found added in the changes: %s" % \
760
                 str(extra_added))
761
    if len(extra_removed) > 0:
762
      self.fail("Some extra paths found removed in the changes: %s" % \
763
                 str(extra_removed))
764
    if len(extra_modified) > 0:
765
      self.fail("Some extra paths found modified in the changes: %s" % \
766
                 str(extra_modified))
767
    if len(extra_renamed) > 0:
768
      self.fail("Some extra paths found renamed in the changes: %s" % \
769
                 str(extra_renamed))
136 by James Westby
Add tests for non-native -> native transition on import.
770
138 by James Westby
Test the native -> non-native transition.
771
  def test_native_to_non_native(self):
772
    self.make_native_dsc_1()
773
    shutil.rmtree(os.path.join(self.basedir, 'debian'))
774
    self.make_dsc_2()
775
    importer = DscImporter([self.native_dsc_1, self.dsc_2])
776
    importer.import_dsc(self.target)
777
    tree = WorkingTree.open(self.target)
778
    expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'from_debian',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
779
                    'debian/', 'debian/changelog', 'debian/install',
780
                    'debian/rules']
138 by James Westby
Test the native -> non-native transition.
781
    tree.lock_read()
782
    try:
783
      self.check_inventory_shape(tree.inventory, expected_inv)
784
    finally:
785
      tree.unlock()
786
    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(), False)
787
    rh = tree.branch.revision_history()
788
    self.assertEqual(len(rh), 3)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
789
    self.check_revision_message(tree, rh[0],
138 by James Westby
Test the native -> non-native transition.
790
                     "import package from %s" % \
791
                     os.path.basename(self.native_1))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
792
    self.check_revision_message(tree, rh[1],
138 by James Westby
Test the native -> non-native transition.
793
                     "import upstream from %s" % \
794
                     os.path.basename(self.orig_2))
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
795
    self.check_revision_message(tree, rh[2],
138 by James Westby
Test the native -> non-native transition.
796
                     "merge packaging changes from %s" % \
797
                     os.path.basename(self.diff_2))
798
    self.assertEqual(len(tree.get_parent_ids()), 1)
799
    parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
800
    self.assertEqual(len(parents), 1)
801
    parents = tree.branch.repository.revision_tree(rh[2]).get_parent_ids()
802
    self.assertEqual(len(parents), 1)
803
    up_tree = tree.branch.repository.revision_tree(rh[1])
804
    changes = tree.changes_from(up_tree)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
805
    expected_added = ['debian/', 'debian/changelog', 'debian/install',
806
                      'debian/rules']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
807
    self.check_changes(changes, added=expected_added)
808
    native_tree = tree.branch.repository.revision_tree(rh[0])
809
    changes = up_tree.changes_from(native_tree)
810
    expected_added = ['NEWS', 'from_debian']
811
    expected_modified = ['Makefile']
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
812
    expected_removed = ['debian/', 'debian/changelog', 'debian/rules'] \
813
                       + self.config_files
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
814
    self.check_changes(changes, added=expected_added, removed=expected_removed,
815
                       modified=expected_modified)
138 by James Westby
Test the native -> non-native transition.
816
    # FIXME: Should changelog etc. be added/removed or not?
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
817
    changes = tree.changes_from(native_tree)
818
    expected_added = ['NEWS', 'debian/', 'debian/install', 'from_debian',
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
819
                      'debian/changelog', 'debian/rules']
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
820
    expected_modified = ['Makefile']
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
821
    expected_removed = ['debian/', 'debian/changelog', 'debian/rules'] \
822
                       + self.config_files
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
823
    self.check_changes(changes, added=expected_added,
824
                       modified=expected_modified, removed=expected_removed)
825
    self.check_is_native_in_config(native_tree)
826
    self.check_is_not_native_in_config(up_tree)
827
    self.check_is_not_native_in_config(tree)
175 by James Westby
Finish of the chmod(debian/rules, 0755) change.
828
    self.assertRulesExecutable(tree)
829
    self.assertRulesExecutable(native_tree)
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
830
831
  def _get_tree_default_config(self, tree, fail_on_none=True):
832
    config_file_id = tree.path2id('.bzr-builddeb/default.conf')
833
    if config_file_id is None:
834
      if fail_on_none:
835
        self.fail("The tree has no config file")
836
      else:
837
        return None
838
    config_file = tree.get_file_text(config_file_id).split('\n')
839
    config = ConfigObj(config_file)
840
    return config
841
842
  def check_is_native_in_config(self, tree):
195 by James Westby
* Fix the import diff code to not deadlock on large diffs. Thanks to
843
    tree.lock_read()
844
    try:
845
      config = self._get_tree_default_config(tree)
846
      self.assertEqual(bool(config['BUILDDEB']['native']), True)
847
    finally:
848
      tree.unlock()
139 by James Westby
Make the config say 'native = True' when it is so that the packages will build.
849
850
  def check_is_not_native_in_config(self, tree):
851
    config = self._get_tree_default_config(tree, fail_on_none=False)
852
    if config is not None:
853
      self.assertEqual(bool(config['BUILDDEB']['native']), False)
138 by James Westby
Test the native -> non-native transition.
854
178.1.29 by James Westby
Add support for incremental import dsc.
855
  def test_import_incremental_simple(self):
856
    # set up the branch using a simple single version non-native import.
857
    self.import_dsc_1()
858
    self.make_dsc_1b()
859
    DscImporter([self.dsc_1b]).incremental_import_dsc(self.target)
860
    self.failUnlessExists(self.target)
861
    tree = WorkingTree.open(self.target)
862
    tree.lock_read()
863
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
864
                    'debian/changelog', 'debian/control', 'debian/rules']
865
    try:
866
      self.check_inventory_shape(tree.inventory, expected_inv)
867
    finally:
868
      tree.unlock()
869
    for path in expected_inv:
870
      self.failUnlessExists(os.path.join(self.target, path))
871
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
872
                           'good command\n')
873
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
874
                           'version 1-1\nversion 1-2\n')
875
    self.assertRulesExecutable(tree)
876
    rh = tree.branch.revision_history()
877
    self.assertEqual(len(rh), 2)
878
    self.check_revision_message(tree, rh[0],
879
                          'import upstream from %s' % self.orig_1)
880
    self.check_revision_message(tree, rh[1],
881
                          'merge packaging changes from %s' % self.diff_1)
882
    parents = tree.get_parent_ids()
883
    self.assertEqual(len(parents), 2)
884
    self.assertEqual(parents[0], rh[1])
885
    self.check_revision_message(tree, parents[1],
886
                          'merge packaging changes from %s' % self.diff_1b)
887
    prev_tree = tree.branch.repository.revision_tree(parents[1])
888
    current_tree = tree.branch.repository.revision_tree(rh[1])
889
    changes = prev_tree.changes_from(current_tree)
890
    expected_added = ['debian/control']
891
    expected_removed = ['debian/install']
892
    expected_modified = ['debian/changelog']
893
    self.check_changes(changes, added=expected_added,
894
                       removed=expected_removed, modified=expected_modified)
895
    self.assertRulesExecutable(prev_tree)
896
    self.assertEqual(len(tree.conflicts()), 0)
897
    changes = tree.changes_from(tree.basis_tree())
898
    self.check_changes(changes, added=expected_added,
899
                       removed=expected_removed, modified=expected_modified)
900
901
  def test_import_incremental_multiple_dscs_prohibited(self):
902
    self.import_dsc_1()
903
    self.make_dsc_1b()
904
    self.make_dsc_2()
905
    importer = DscImporter([self.dsc_1b, self.dsc_2])
906
    self.assertRaises(OnlyImportSingleDsc, importer.incremental_import_dsc,
907
      self.target)
908
178.1.30 by James Westby
Hook up the import-dsc command to allow incremental imports.
909
  def test_import_incremental_working_tree_changes(self):
910
    self.import_dsc_1()
911
    self.make_dsc_1b()
912
    self.build_tree([os.path.join(self.target, 'a')])
913
    tree = WorkingTree.open(self.target)
914
    tree.add(['a'])
915
    importer = DscImporter([self.dsc_1b])
916
    self.assertRaises(UncommittedChanges, importer.incremental_import_dsc,
917
            self.target)
918
178.1.29 by James Westby
Add support for incremental import dsc.
919
  def test_incremental_with_upstream(self):
920
    self.import_dsc_1()
921
    self.make_dsc_2()
922
    DscImporter([self.dsc_2]).incremental_import_dsc(self.target)
923
    self.failUnlessExists(self.target)
924
    tree = WorkingTree.open(self.target)
925
    tree.lock_read()
926
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'from_debian',
927
                    'debian/', 'debian/changelog', 'debian/install',
928
                    'debian/rules']
929
    try:
930
      self.check_inventory_shape(tree.inventory, expected_inv)
931
    finally:
932
      tree.unlock()
933
    for path in expected_inv:
934
      self.failUnlessExists(os.path.join(self.target, path))
935
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
936
                           'good command\n')
937
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
938
        '<<<<<<< TREE\nversion 1-1\n=======\nversion 1-1\nversion 1-2\n'
939
        'version 1-3\nversion 2-1\n>>>>>>> MERGE-SOURCE\n')
940
    self.assertRulesExecutable(tree)
941
    rh = tree.branch.revision_history()
942
    self.assertEqual(len(rh), 2)
943
    self.check_revision_message(tree, rh[0],
944
                          'import upstream from %s' % self.orig_1)
945
    self.check_revision_message(tree, rh[1],
946
                          'merge packaging changes from %s' % self.diff_1)
947
    parents = tree.get_parent_ids()
948
    self.assertEqual(len(parents), 2)
949
    self.assertEqual(parents[0], rh[1])
950
    self.check_revision_message(tree, parents[1],
951
                          'merge packaging changes from %s' % self.diff_2)
952
    prev_tree = tree.branch.repository.revision_tree(parents[1])
953
    current_tree = tree.branch.repository.revision_tree(parents[0])
954
    changes = prev_tree.changes_from(current_tree)
955
    expected_added = ['from_debian', 'NEWS']
956
    expected_modified = ['debian/changelog']
957
    self.check_changes(changes, added=expected_added,
958
                       removed=[], modified=expected_modified)
959
    self.assertRulesExecutable(prev_tree)
960
    self.assertEqual(len(tree.conflicts()), 1)
961
    self.assertTrue(isinstance(tree.conflicts()[0], TextConflict))
962
    self.assertEqual(tree.conflicts()[0].path, 'debian/changelog')
963
    changes = tree.changes_from(tree.basis_tree())
964
    self.check_changes(changes, added=expected_added,
965
                       removed=[], modified=expected_modified)
966
    merged_parents = prev_tree.get_parent_ids()
967
    self.assertEqual(len(merged_parents), 1)
968
    self.check_revision_message(tree, merged_parents[0],
969
                          'import upstream from %s' % self.orig_2)
970
    new_upstream_tree = tree.branch.repository.revision_tree(merged_parents[0])
971
    new_upstream_parents = new_upstream_tree.get_parent_ids()
972
    self.assertEqual(len(new_upstream_parents), 1)
973
    self.assertEqual(new_upstream_parents[0], rh[0])
974
975
  def test_incremental_with_upstream_older_than_all_in_branch(self):
976
    self.make_dsc_1()
977
    self.make_dsc_2()
978
    DscImporter([self.dsc_2]).import_dsc(self.target)
979
    self.failUnlessExists(self.target)
980
    DscImporter([self.dsc_1]).incremental_import_dsc(self.target)
981
    self.failUnlessExists(self.target)
982
    tree = WorkingTree.open(self.target)
983
    tree.lock_read()
984
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'from_debian',
985
                    'debian/', 'debian/changelog',
986
                    'debian/install', 'debian/rules']
987
    try:
988
      self.check_inventory_shape(tree.inventory, expected_inv)
989
    finally:
990
      tree.unlock()
991
    for path in expected_inv:
992
      self.failUnlessExists(os.path.join(self.target, path))
993
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
994
                           'good command\n')
995
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
996
        '<<<<<<< TREE\nversion 1-1\nversion 1-2\nversion 1-3\nversion 2-1\n'
997
        '=======\nversion 1-1\n>>>>>>> MERGE-SOURCE\n')
998
    self.assertRulesExecutable(tree)
999
    rh = tree.branch.revision_history()
1000
    self.assertEqual(len(rh), 2)
1001
    self.check_revision_message(tree, rh[0],
1002
                          'import upstream from %s' % self.orig_2)
1003
    self.check_revision_message(tree, rh[1],
1004
                          'merge packaging changes from %s' % self.diff_2)
1005
    parents = tree.get_parent_ids()
1006
    self.assertEqual(len(parents), 2)
1007
    self.assertEqual(parents[0], rh[1])
1008
    self.check_revision_message(tree, parents[1],
1009
                          'merge packaging changes from %s' % self.diff_1)
1010
    prev_tree = tree.branch.repository.revision_tree(parents[1])
1011
    merged_parents = prev_tree.get_parent_ids()
1012
    self.assertEqual(len(merged_parents), 1)
1013
    self.check_revision_message(tree, merged_parents[0],
1014
                          'import upstream from %s' % self.orig_1)
1015
1016
  def test_incremental_with_upstream_older_than_lastest_in_branch(self):
1017
    self.make_dsc_1()
1018
    self.make_dsc_2()
1019
    self.make_dsc_3()
1020
    DscImporter([self.dsc_1, self.dsc_3]).import_dsc(self.target)
1021
    self.failUnlessExists(self.target)
1022
    DscImporter([self.dsc_2,]).incremental_import_dsc(self.target)
1023
    self.failUnlessExists(self.target)
1024
    tree = WorkingTree.open(self.target)
1025
    tree.lock_read()
1026
    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'from_debian',
1027
                    'NEW_IN_3', 'debian/', 'debian/changelog',
1028
                    'debian/install', 'debian/rules']
1029
    try:
1030
      self.check_inventory_shape(tree.inventory, expected_inv)
1031
    finally:
1032
      tree.unlock()
1033
    for path in expected_inv:
1034
      self.failUnlessExists(os.path.join(self.target, path))
1035
    self.assertContentsAre(os.path.join(self.target, 'Makefile'),
1036
                           'good command\n')
1037
    self.assertContentsAre(os.path.join(self.target, 'debian', 'changelog'),
1038
        '<<<<<<< TREE\nversion 1-1\nversion 1-2\nversion 1-3\nversion 2-1\n'
1039
        'version 3-1\n=======\nversion 1-1\nversion 1-2\nversion 1-3\n'
1040
        'version 2-1\n>>>>>>> MERGE-SOURCE\n')
1041
    self.assertRulesExecutable(tree)
1042
    rh = tree.branch.revision_history()
1043
    self.assertEqual(len(rh), 3)
1044
    self.check_revision_message(tree, rh[0],
1045
                          'import upstream from %s' % self.orig_1)
1046
    self.check_revision_message(tree, rh[1],
1047
                          'import upstream from %s' % self.orig_3)
1048
    self.check_revision_message(tree, rh[2],
1049
                          'merge packaging changes from %s' % self.diff_3)
1050
    parents = tree.get_parent_ids()
1051
    self.assertEqual(len(parents), 2)
1052
    self.assertEqual(parents[0], rh[2])
1053
    self.check_revision_message(tree, parents[1],
1054
                          'merge packaging changes from %s' % self.diff_2)
1055
    prev_tree = tree.branch.repository.revision_tree(parents[1])
1056
    merged_parents = prev_tree.get_parent_ids()
1057
    self.assertEqual(len(merged_parents), 1)
1058
    self.check_revision_message(tree, merged_parents[0],
1059
                          'import upstream from %s' % self.orig_2)
1060
    new_upstream_tree = tree.branch.repository.revision_tree(merged_parents[0])
1061
    new_upstream_parents = new_upstream_tree.get_parent_ids()
1062
    self.assertEqual(len(new_upstream_parents), 1)
1063
    self.assertEqual(new_upstream_parents[0], rh[0])
1064
    self.check_revision_message(tree, merged_parents[0],
1065
                          'import upstream from %s' % self.orig_2)
1066
201 by James Westby
* Be more careful in excluding the root entry when extracting a tarball
1067
  def test_import_no_prefix(self):
1068
    write_to_file('README', 'hello\n')
1069
    write_to_file('NEWS', 'bye bye\n')
1070
    tar = tarfile.open(self.native_1, 'w:gz')
1071
    try:
1072
      tar.add('./', recursive=False)
1073
      tar.add('README')
1074
      tar.add('NEWS')
1075
    finally:
1076
      tar.close()
1077
      os.unlink('README')
1078
      os.unlink('NEWS')
1079
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1080
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1081
    self.failUnlessExists(self.target)
1082
204 by James Westby
Don't eat the first two characters of a filename when the prefix is '.'
1083
  def test_import_dot_prefix(self):
1084
    write_to_file('README', 'hello\n')
1085
    write_to_file('NEWS', 'bye bye\n')
1086
    tar = tarfile.open(self.native_1, 'w:gz')
1087
    try:
1088
      tar.addfile(_TarInfo('./'))
1089
      tar.addfile(_TarInfo('./README'))
1090
      tar.addfile(_TarInfo('./NEWS'))
1091
    finally:
1092
      tar.close()
1093
      os.unlink('README')
1094
      os.unlink('NEWS')
1095
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1096
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1097
    self.failUnlessExists(self.target)
1098
    self.failIfExists(os.path.join(self.target, 'ADME'))
1099
    self.failUnlessExists(os.path.join(self.target, 'README'))
1100
208 by James Westby
Handle the dot entry existing as well as a prefix.
1101
  def test_import_dot_and_prefix(self):
1102
    dir = 'dir'
1103
    os.mkdir(dir)
1104
    write_to_file(os.path.join(dir, 'README'), 'hello\n')
1105
    write_to_file(os.path.join(dir, 'NEWS'), 'bye bye\n')
1106
    tar = tarfile.open(self.native_1, 'w:gz')
1107
    try:
1108
      tar.addfile(_TarInfo('./'))
1109
      tar.addfile(_TarInfo(dir))
1110
      tar.addfile(_TarInfo(os.path.join(dir, 'README')))
1111
      tar.addfile(_TarInfo(os.path.join(dir, 'NEWS')))
1112
    finally:
1113
      tar.close()
1114
      shutil.rmtree(dir)
1115
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1116
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1117
    self.failUnlessExists(self.target)
1118
    self.failIfExists(os.path.join(self.target, dir))
1119
209 by James Westby
Handle absolute pathnames in the tarfile.
1120
  def test_import_absolute_path(self):
1121
    dir = 'dir'
1122
    os.mkdir(dir)
1123
    write_to_file(os.path.join(dir, 'README'), 'hello\n')
1124
    write_to_file(os.path.join(dir, 'NEWS'), 'bye bye\n')
1125
    tar = tarfile.open(self.native_1, 'w:gz')
1126
    try:
1127
      tar.addfile(_TarInfo(dir))
1128
      tar.addfile(_TarInfo('/' + os.path.join(dir, 'README')))
1129
      tar.addfile(_TarInfo(os.path.join(dir, 'NEWS')))
1130
    finally:
1131
      tar.close()
1132
      shutil.rmtree(dir)
1133
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1134
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1135
    self.failUnlessExists(self.target)
1136
    self.failIfExists(os.path.join(self.target, dir))
1137
    self.failUnlessExists(os.path.join(self.target, 'README'))
1138
    self.failUnlessExists(os.path.join(self.target, 'NEWS'))
1139
203 by James Westby
Also exclude RCS ,v files when importing.
1140
  def test_import_with_rcs(self):
1141
    write_to_file('README', 'hello\n')
1142
    write_to_file('README,v', 'bye bye\n')
1143
    tar = tarfile.open(self.native_1, 'w:gz')
1144
    try:
1145
      tar.add('README')
1146
      tar.add('README,v')
1147
    finally:
1148
      tar.close()
1149
      os.unlink('README')
1150
      os.unlink('README,v')
1151
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1152
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1153
    self.failUnlessExists(self.target)
1154
    self.failIfExists(os.path.join(self.target, 'README,v'))
1155
1156
  def test_patch_with_rcs(self):
1157
    self.make_orig_1()
1158
    diffdir = 'package-0.1'
1159
    shutil.copytree(self.basedir, diffdir)
1160
    f = gzip.open(self.diff_1, 'w')
1161
    try:
1162
      f.write(
1163
"""diff -Nru package/file,v package-0.2/file,v
1164
--- package/file,v      1970-01-01 01:00:00.000000000 +0100
1165
+++ package-0.2/file,v  2008-01-25 12:48:26.823475582 +0000
1166
@@ -0,0 +1 @@
1167
+with a passion
1168
\ No newline at end of file
1169
diff -Nru package/file package-0.2/file
1170
--- package/file      1970-01-01 01:00:00.000000000 +0100
1171
+++ package-0.2/file  2008-01-25 12:48:26.823475582 +0000
1172
@@ -0,0 +1 @@
1173
+with a passion
1174
\ No newline at end of file
1175
""")
1176
    finally:
1177
      f.close()
1178
    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, [self.diff_1])
1179
    DscImporter([self.dsc_1]).import_dsc(self.target)
1180
    self.failUnlessExists(self.target)
1181
    self.failIfExists(os.path.join(self.target, 'changelog'))
1182
    self.failIfExists(os.path.join(self.target, 'changelog,v'))
1183
202 by James Westby
* Normalise filenames from the tarballs when extracting to import a
1184
  def test_import_extra_slash(self):
1185
    tar = tarfile.open(self.native_1, 'w:gz')
1186
    try:
1187
      tar.addfile(_TarInfo('root//'))
1188
      tar.addfile(_TarInfo('root//README'))
1189
      tar.addfile(_TarInfo('root//NEWS'))
1190
    finally:
1191
      tar.close()
1192
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1193
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1194
    self.failUnlessExists(self.target)
1195
207 by James Westby
* Treat hardlinks in tarballs as a copy of the file. This at least
1196
  def test_import_hardlink(self):
1197
    write_to_file('README', 'hello\n')
1198
    os.system('ln README NEWS')
1199
    tar = tarfile.open(self.native_1, 'w:gz')
1200
    try:
1201
      tar.add('./', recursive=False)
1202
      tar.add('./README')
1203
      tar.add('./NEWS')
1204
    finally:
1205
      tar.close()
1206
      os.unlink('README')
1207
      os.unlink('NEWS')
1208
    self.make_dsc(self.native_dsc_1, '0.1', self.native_1)
1209
    DscImporter([self.native_dsc_1]).import_dsc(self.target)
1210
    self.failUnlessExists(self.target)
1211
    self.failUnlessExists(os.path.join(self.target, 'NEWS'))
1212
    self.failUnlessExists(os.path.join(self.target, 'README'))
1213
1214
202 by James Westby
* Normalise filenames from the tarballs when extracting to import a
1215
class _TarInfo(tarfile.TarInfo):
1216
    """Subclass TarInfo to stop it normalising its path. Sorry Mum."""
1217
219 by James Westby
Make running the tests during the build much more robust.
1218
if sys.version > (2, 4):
1219
        def tobuf(self, posix=False):
1220
            """Return a tar header as a string of 512 byte blocks.
1221
            """
1222
            buf = ""
1223
            type = self.type
1224
            prefix = ""
1225
1226
            if self.name.endswith("/"):
1227
                type = tarfile.DIRTYPE
1228
1229
            name = self.name
1230
1231
            if type == tarfile.DIRTYPE:
1232
                # directories should end with '/'
1233
                name += "/"
1234
1235
            linkname = self.linkname
1236
            if linkname:
1237
                # if linkname is empty we end up with a '.'
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1238
                linkname = os.path.normpath(linkname)
219 by James Westby
Make running the tests during the build much more robust.
1239
1240
            if posix:
1241
                if self.size > tarfile.MAXSIZE_MEMBER:
1242
                    raise ValueError("file is too large (>= 8 GB)")
1243
1244
                if len(self.linkname) > tarfile.LENGTH_LINK:
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1245
                    raise ValueError("linkname is too long (>%d)" \
1246
                            % (tarfile.LENGTH_LINK))
219 by James Westby
Make running the tests during the build much more robust.
1247
1248
                if len(name) > tarfile.LENGTH_NAME:
1249
                    prefix = name[:tarfile.LENGTH_PREFIX + 1]
1250
                    while prefix and prefix[-1] != "/":
1251
                        prefix = prefix[:-1]
1252
1253
                    name = name[len(prefix):]
202 by James Westby
* Normalise filenames from the tarballs when extracting to import a
1254
                    prefix = prefix[:-1]
1255
219 by James Westby
Make running the tests during the build much more robust.
1256
                    if not prefix or len(name) > tarfile.LENGTH_NAME:
1257
                        raise ValueError("name is too long")
1258
1259
            else:
1260
                if len(self.linkname) > tarfile.LENGTH_LINK:
1261
                    buf += self._create_gnulong(self.linkname,
1262
                                                tarfile.GNUTYPE_LONGLINK)
1263
1264
                if len(name) > tarfile.LENGTH_NAME:
1265
                    buf += self._create_gnulong(name, tarfile.GNUTYPE_LONGNAME)
1266
1267
            parts = [
1268
                tarfile.stn(name, 100),
1269
                tarfile.itn(self.mode & 07777, 8, posix),
1270
                tarfile.itn(self.uid, 8, posix),
1271
                tarfile.itn(self.gid, 8, posix),
1272
                tarfile.itn(self.size, 12, posix),
1273
                tarfile.itn(self.mtime, 12, posix),
1274
                "        ", # checksum field
1275
                type,
1276
                tarfile.stn(self.linkname, 100),
1277
                tarfile.stn(tarfile.MAGIC, 6),
1278
                tarfile.stn(tarfile.VERSION, 2),
1279
                tarfile.stn(self.uname, 32),
1280
                tarfile.stn(self.gname, 32),
1281
                tarfile.itn(self.devmajor, 8, posix),
1282
                tarfile.itn(self.devminor, 8, posix),
1283
                tarfile.stn(prefix, 155)
1284
            ]
1285
1286
            buf += "".join(parts).ljust(tarfile.BLOCKSIZE, tarfile.NUL)
1287
            chksum = tarfile.calc_chksums(buf[-tarfile.BLOCKSIZE:])[0]
1288
            buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
1289
            self.buf = buf
1290
            return buf
202 by James Westby
* Normalise filenames from the tarballs when extracting to import a
1291
178.1.29 by James Westby
Add support for incremental import dsc.
1292
# vim: sw=2 sts=2 ts=2 
1293
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1294
class DistributionBranchTests(TestCaseWithTransport):
1295
1296
    def setUp(self):
1297
        super(DistributionBranchTests, self).setUp()
1298
        self.tree1 = self.make_branch_and_tree('unstable')
1299
        self.up_tree1 = self.make_branch_and_tree('unstable-upstream')
1300
        self.name1 = "debian-unstable"
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
1301
        self.db1 = DistributionBranch(self.name1, self.tree1.branch,
1302
                self.up_tree1.branch, tree=self.tree1,
1303
                upstream_tree=self.up_tree1)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1304
        self.tree2 = self.make_branch_and_tree('experimental')
1305
        self.up_tree2 = self.make_branch_and_tree('experimental-upstream')
1306
        self.name2 = "debian-experimental"
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
1307
        self.db2 = DistributionBranch(self.name2, self.tree2.branch,
1308
                self.up_tree2.branch, tree=self.tree2,
1309
                upstream_tree=self.up_tree2)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1310
        self.tree3 = self.make_branch_and_tree('gutsy')
1311
        self.up_tree3 = self.make_branch_and_tree('gutsy-upstream')
1312
        self.name3 = "ubuntu-gutsy"
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
1313
        self.db3 = DistributionBranch(self.name3, self.tree3.branch,
1314
                self.up_tree3.branch, tree=self.tree3,
1315
                upstream_tree=self.up_tree3)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1316
        self.tree4 = self.make_branch_and_tree('hardy')
1317
        self.up_tree4 = self.make_branch_and_tree('hardy-upstream')
1318
        self.name4 = "ubuntu-hardy"
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
1319
        self.db4 = DistributionBranch(self.name4, self.tree4.branch,
1320
                self.up_tree4.branch, tree=self.tree4,
1321
                upstream_tree=self.up_tree4)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1322
        self.set = DistributionBranchSet()
1323
        self.set.add_branch(self.db1)
1324
        self.set.add_branch(self.db2)
1325
        self.set.add_branch(self.db3)
1326
        self.set.add_branch(self.db4)
1327
        self.fake_md5_1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1328
        self.fake_md5_2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
1329
1330
    def assertContentsAre(self, filename, expected_contents):
1331
        f = open(filename)
1332
        try:
1333
          contents = f.read()
1334
        finally:
1335
          f.close()
1336
        self.assertEqual(contents, expected_contents,
1337
                         "Contents of %s are not as expected" % filename)
1338
1339
    def do_commit_with_md5(self, tree, message, md5):
1340
        return tree.commit(message, revprops={"deb-md5":md5})
1341
1342
    def test_create(self):
1343
        db = self.db1
1344
        self.assertNotEqual(db, None)
1345
        self.assertEqual(db.name, self.name1)
236 by James Westby
Only access the branch of other DistributionBranch, not the tree.
1346
        self.assertEqual(db.branch, self.tree1.branch)
1347
        self.assertEqual(db.upstream_branch, self.up_tree1.branch)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
1348
        self.assertEqual(db.tree, self.tree1)
1349
        self.assertEqual(db.upstream_tree, self.up_tree1)
1350
1351
    def test_tag_name(self):
1352
        db = self.db1
1353
        version_no = "0.1-1"
1354
        version = Version(version_no)
1355
        self.assertEqual(db.tag_name(version),
1356
                self.name1 + "-" + version_no)
1357
1358
    def test_upstream_tag_name(self):
1359
        db = self.db1
1360
        upstream_v_no = "0.1"
1361
        version_no = upstream_v_no + "-1"
1362
        version = Version(version_no)
1363
        self.assertEqual(db.upstream_tag_name(version),
1364
                "upstream-" + self.name1 + "-" + upstream_v_no)
1365
1366
    def test_tag_version(self):
1367
        db = self.db1
1368
        tree = self.tree1
1369
        version = Version("0.1-1")
1370
        revid = tree.commit("one")
1371
        db.tag_version(version)
1372
        self.assertEqual(tree.branch.tags.lookup_tag(db.tag_name(version)),
1373
                revid)
1374
1375
    def test_tag_upstream_version(self):
1376
        db = self.db1
1377
        tree = self.up_tree1
1378
        version = Version("0.1-1")
1379
        revid = tree.commit("one")
1380
        db.tag_upstream_version(version)
1381
        tag_name = db.upstream_tag_name(version)
1382
        self.assertEqual(tree.branch.tags.lookup_tag(tag_name), revid)
1383
1384
    def test_has_version(self):
1385
        db = self.db1
1386
        version = Version("0.1-1")
1387
        self.assertFalse(db.has_version(version))
1388
        self.assertFalse(db.has_version(version, self.fake_md5_1))
1389
        self.do_commit_with_md5(self.tree1, "one", self.fake_md5_1)
1390
        db.tag_version(version)
1391
        self.assertTrue(db.has_version(version))
1392
        self.assertTrue(db.has_version(version, self.fake_md5_1))
1393
        self.assertFalse(db.has_version(version, self.fake_md5_2))
1394
        version = Version("0.1-2")
1395
        self.assertFalse(db.has_version(version))
1396
        self.assertFalse(db.has_version(version, self.fake_md5_1))
1397
        self.assertFalse(db.has_version(version, self.fake_md5_2))
1398
1399
    def test_has_upstream_version(self):
1400
        db = self.db1
1401
        version = Version("0.1-1")
1402
        self.assertFalse(db.has_upstream_version(version))
1403
        self.assertFalse(db.has_upstream_version(version, self.fake_md5_1))
1404
        self.do_commit_with_md5(self.up_tree1, "one", self.fake_md5_1)
1405
        db.tag_upstream_version(version)
1406
        self.assertTrue(db.has_upstream_version(version))
1407
        self.assertTrue(db.has_upstream_version(version, self.fake_md5_1))
1408
        self.assertFalse(db.has_upstream_version(version, self.fake_md5_2))
1409
        version = Version("0.1-2")
1410
        self.assertTrue(db.has_upstream_version(version))
1411
        self.assertTrue(db.has_upstream_version(version, self.fake_md5_1))
1412
        self.assertFalse(db.has_upstream_version(version, self.fake_md5_2))
1413
        version = Version("0.2-1")
1414
        self.assertFalse(db.has_upstream_version(version))
1415
        self.assertFalse(db.has_upstream_version(version, self.fake_md5_1))
1416
        self.assertFalse(db.has_upstream_version(version, self.fake_md5_2))
1417
1418
    def test_revid_of_version(self):
1419
        db = self.db1
1420
        tree = self.tree1
1421
        version = Version("0.1-1")
1422
        revid = tree.commit("one")
1423
        db.tag_version(version)
1424
        self.assertEqual(db.revid_of_version(version), revid)
1425
1426
    def test_revid_of_upstream_version(self):
1427
        db = self.db1
1428
        tree = self.up_tree1
1429
        version = Version("0.1-1")
1430
        revid = tree.commit("one")
1431
        db.tag_upstream_version(version)
1432
        self.assertEqual(db.revid_of_upstream_version(version), revid)
1433
1434
    def test_contained_versions(self):
1435
        db = self.db1
1436
        version1 = Version("0.1-1")
1437
        version2 = Version("0.1-2")
1438
        version3 = Version("0.1-3")
1439
        version4 = Version("0.1-4")
1440
        version5 = Version("0.1-5")
1441
        self.assertEqual(db.contained_versions([]), ([], []))
1442
        self.assertEqual(db.contained_versions([version1]),
1443
                ([], [version1]))
1444
        self.tree1.commit("one")
1445
        db.tag_version(version1)
1446
        db.tag_version(version3)
1447
        db.tag_version(version4)
1448
        version_list = [version5, version4, version3, version2, version1]
1449
        self.assertEqual(db.contained_versions(version_list),
1450
                ([version4, version3, version1], [version5, version2]))
1451
        self.assertEqual(db.contained_versions([]), ([], []))
1452
1453
    def test_missing_versions(self):
1454
        db = self.db1
1455
        version1 = Version("0.1-1")
1456
        version2 = Version("0.1-2")
1457
        version3 = Version("0.1-3")
1458
        version4 = Version("0.1-4")
1459
        version5 = Version("0.1-5")
1460
        self.assertEqual(db.missing_versions([]), [])
1461
        self.assertEqual(db.missing_versions([version1]), [version1])
1462
        self.tree1.commit("one")
1463
        db.tag_version(version1)
1464
        db.tag_version(version3)
1465
        version_list = [version5, version4, version3, version2, version1]
1466
        self.assertEqual(db.missing_versions(version_list),
1467
                [version5, version4])
1468
        self.assertEqual(db.missing_versions([]), [])
1469
1470
    def test_last_contained_version(self):
1471
        db = self.db1
1472
        version1 = Version("0.1-1")
1473
        version2 = Version("0.1-2")
1474
        version3 = Version("0.1-3")
1475
        self.assertEqual(db.last_contained_version([]), None)
1476
        self.assertEqual(db.last_contained_version([version1]), None)
1477
        self.tree1.commit("one")
1478
        db.tag_version(version1)
1479
        db.tag_version(version3)
1480
        self.assertEqual(db.last_contained_version([version2]), None)
1481
        self.assertEqual(db.last_contained_version([]), None)
1482
        self.assertEqual(db.last_contained_version([version2, version1]),
1483
                version1)
1484
        self.assertEqual(db.last_contained_version([version3, version2,
1485
                                                    version1]), version3)
1486
1487
    def test_get_parents_first_version(self):
1488
        """If there are no previous versions then there are no parents."""
1489
        db = self.db1
1490
        version1 = Version("0.1-1")
1491
        self.assertEqual(db.get_parents([version1]), [])
1492
        db = self.db2
1493
        self.assertEqual(db.get_parents([version1]), [])
1494
1495
    def test_get_parents_second_version(self):
1496
        """Previous with same upstream should give that as parent."""
1497
        db = self.db1
1498
        version1 = Version("0.1-1")
1499
        version2 = Version("0.1-2")
1500
        revid1 = self.tree1.commit("one")
1501
        db.tag_version(version1)
1502
        self.assertEqual(db.get_parents([version2, version1]),
1503
                [(db, version1, revid1)])
1504
1505
    def test_get_parents_merge_from_lesser(self):
1506
        """Merge with same upstream version gives merged as second parent."""
1507
        version1 = Version("0.1-1")
1508
        version2 = Version("0.1-0ubuntu1")
1509
        version3 = Version("0.1-1ubuntu1")
1510
        revid1 = self.tree1.commit("one")
1511
        revid2 = self.tree2.commit("two")
1512
        self.db1.tag_version(version1)
1513
        self.db2.tag_version(version2)
1514
        versions = [version3, version1, version2]
1515
        # test is that revid1 is second parent
1516
        self.assertEqual(self.db2.get_parents(versions),
1517
                [(self.db2, version2, revid2),
1518
                (self.db1, version1, revid1)])
1519
1520
    def test_get_parents_merge_from_greater(self):
1521
        """Merge from greater is same as merge from lesser."""
1522
        version1 = Version("0.1-1")
1523
        version2 = Version("0.1-1ubuntu1")
1524
        version3 = Version("0.1-2")
1525
        revid1 = self.tree1.commit("one")
1526
        revid2 = self.tree2.commit("two")
1527
        self.db1.tag_version(version1)
1528
        self.db2.tag_version(version2)
1529
        versions = [version3, version2, version1]
1530
        # test is that revid2 is second parent
1531
        self.assertEqual(self.db1.get_parents(versions),
1532
                [(self.db1, version1, revid1),
1533
                (self.db2, version2, revid2)])
1534
1535
    def test_get_parents_merge_from_two_lesser(self):
1536
        """Should use greatest lesser when two candidates."""
1537
        version1 = Version("0.1-1")
1538
        version2 = Version("0.1-0ubuntu1")
1539
        version3 = Version("0.1-1ubuntu1")
1540
        revid1 = self.tree1.commit("one")
1541
        revid2 = self.tree2.commit("two")
1542
        revid3 = self.tree3.commit("three")
1543
        self.db1.tag_version(version1)
1544
        self.db2.tag_version(version1)
1545
        self.db3.tag_version(version2)
1546
        versions = [version3, version1, version2]
1547
        # test is that revid2 and not revid1 is second parent
1548
        self.assertEqual(self.db3.get_parents(versions),
1549
                [(self.db3, version2, revid3),
1550
                (self.db2, version1, revid2)])
1551
1552
    def test_get_parents_merge_from_two_greater(self):
1553
        """Should use least greater when two candidates."""
1554
        version1 = Version("0.1-1")
1555
        version2 = Version("0.1-0ubuntu1")
1556
        version3 = Version("0.1-2")
1557
        revid1 = self.tree1.commit("one")
1558
        revid2 = self.tree2.commit("two")
1559
        revid3 = self.tree3.commit("three")
1560
        self.db1.tag_version(version1)
1561
        self.db2.tag_version(version2)
1562
        self.db3.tag_version(version2)
1563
        versions = [version3, version2, version1]
1564
        # test is that revid2 and not revid3 is second parent
1565
        self.assertEqual(self.db1.get_parents(versions),
1566
                [(self.db1, version1, revid1),
1567
                (self.db2, version2, revid2)])
1568
1569
    def test_get_parents_merge_multiple_from_greater(self):
1570
        """More than two parents correctly ordered."""
1571
        version1 = Version("0.1-1")
1572
        version2 = Version("0.1-1ubuntu1")
1573
        version3 = Version("0.1-1other1")
1574
        version4 = Version("0.1-2")
1575
        revid1 = self.tree1.commit("one")
1576
        revid2 = self.tree2.commit("two")
1577
        revid3 = self.tree3.commit("three")
1578
        self.db1.tag_version(version1)
1579
        self.db2.tag_version(version2)
1580
        self.db3.tag_version(version3)
1581
        versions = [version4, version3, version2, version1]
1582
        # test is that revid2 is second, revid3 is third
1583
        self.assertEqual(self.db1.get_parents(versions),
1584
                [(self.db1, version1, revid1), (self.db2, version2, revid2),
1585
                (self.db3, version3, revid3)])
1586
1587
    def test_get_parents_sync_when_diverged(self):
1588
        version1 = Version("0.1-1")
1589
        version2 = Version("0.1-1ubuntu1")
1590
        version3 = Version("0.1-2")
1591
        revid1 = self.tree1.commit("one")
1592
        revid2 = self.tree2.commit("two")
1593
        revid3 = self.tree1.commit("three")
1594
        self.db1.tag_version(version1)
1595
        self.db2.tag_version(version2)
1596
        self.db1.tag_version(version3)
1597
        versions = [version3, version2, version1]
1598
        # This is a sync, but we have diverged, so we should
1599
        # get two parents, the last ubuntu upload,
1600
        # and the Debian upload as the second parent.
1601
        self.assertEqual(self.db2.get_parents(versions),
1602
                [(self.db2, version2, revid2),
1603
                (self.db1, version3, revid3)])
1604
1605
    def test_get_parents_skipped_version(self):
1606
        version1 = Version("0.1-1")
1607
        version2 = Version("0.1-2")
1608
        version3 = Version("0.1-2ubuntu1")
1609
        revid1 = self.tree1.commit("one")
1610
        revid2 = self.tree2.commit("two")
1611
        self.db1.tag_version(version1)
1612
        self.db2.tag_version(version2)
1613
        versions = [version3, version2, version1]
1614
        self.assertEqual(self.db2.get_parents(versions),
1615
                [(self.db2, version2, revid2)])
1616
1617
    def test_get_parents_with_upstream_first_version(self):
1618
        db = self.db1
1619
        version1 = Version("0.1-1")
1620
        up_revid = self.up_tree1.commit("one")
1621
        db.tag_upstream_version(version1)
1622
        self.assertEqual(db.get_parents_with_upstream(version1, [version1]),
1623
                [up_revid])
1624
        db = self.db2
1625
        self.up_tree2.pull(self.up_tree1.branch)
1626
        db.tag_upstream_version(version1)
1627
        self.assertEqual(db.get_parents_with_upstream(version1, [version1]),
1628
                [up_revid])
1629
1630
    def test_get_parents_with_upstream_second_version(self):
1631
        db = self.db1
1632
        version1 = Version("0.1-1")
1633
        version2 = Version("0.1-2")
1634
        revid1 = self.tree1.commit("one")
1635
        db.tag_version(version1)
1636
        up_revid = self.up_tree1.commit("upstream one")
1637
        db.tag_upstream_version(version1)
1638
        # No upstream parent
1639
        self.assertEqual(db.get_parents_with_upstream(version2,
1640
                    [version2, version1]), [revid1])
1641
1642
    def test_get_parents_with_upstream_merge_from_lesser(self):
1643
        version1 = Version("0.1-1")
1644
        version2 = Version("0.1-0ubuntu1")
1645
        version3 = Version("0.1-1ubuntu1")
1646
        revid1 = self.tree1.commit("one")
1647
        revid2 = self.tree2.commit("two")
1648
        self.db1.tag_version(version1)
1649
        self.db2.tag_version(version2)
1650
        up_revid1 = self.up_tree1.commit("upstream one")
1651
        self.up_tree2.pull(self.up_tree1.branch)
1652
        self.db1.tag_upstream_version(version1)
1653
        self.db2.tag_upstream_version(version2)
1654
        versions = [version3, version1, version2]
1655
        # No upstream parent
1656
        self.assertEqual(self.db2.get_parents_with_upstream(version3,
1657
                    versions), [revid2, revid1])
1658
1659
    def test_get_parents_with_upstream_merge_from_greater(self):
1660
        version1 = Version("0.1-1")
1661
        version2 = Version("0.1-1ubuntu1")
1662
        version3 = Version("0.1-2")
1663
        revid1 = self.tree1.commit("one")
1664
        revid2 = self.tree2.commit("two")
1665
        self.db1.tag_version(version1)
1666
        self.db2.tag_version(version2)
1667
        up_revid1 = self.up_tree1.commit("upstream one")
1668
        self.up_tree2.pull(self.up_tree1.branch)
1669
        self.db1.tag_upstream_version(version1)
1670
        self.db2.tag_upstream_version(version2)
1671
        versions = [version3, version2, version1]
1672
        # No upstream parent
1673
        self.assertEqual(self.db1.get_parents_with_upstream(version3,
1674
                    versions), [revid1, revid2])
1675
1676
    def test_get_parents_with_upstream_new_upstream_import(self):
1677
        version1 = Version("0.1-1")
1678
        version2 = Version("0.2-0ubuntu1")
1679
        revid1 = self.tree1.commit("one")
1680
        self.tree2.pull(self.tree1.branch)
1681
        self.db1.tag_version(version1)
1682
        self.db2.tag_version(version1)
1683
        up_revid1 = self.up_tree1.commit("upstream one")
1684
        up_revid2 = self.up_tree2.commit("upstream two")
1685
        self.db1.tag_upstream_version(version1)
1686
        self.db2.tag_upstream_version(version2)
1687
        versions = [version2, version1]
1688
        # Upstream parent as it is new upstream version
1689
        self.assertEqual(self.db2.get_parents_with_upstream(version2,
1690
                    versions), [revid1, up_revid2])
1691
1692
    def test_get_parents_merge_new_upstream_from_lesser(self):
1693
        version1 = Version("0.1-1")
1694
        version2 = Version("0.1-1ubuntu1")
1695
        version3 = Version("0.2-1")
1696
        version4 = Version("0.2-1ubuntu1")
1697
        revid1 = self.tree1.commit("one")
1698
        self.db1.tag_version(version1)
1699
        revid2 = self.tree2.commit("two")
1700
        self.db2.tag_version(version2)
1701
        revid3 = self.tree1.commit("three")
1702
        self.db1.tag_version(version3)
1703
        up_revid1 = self.up_tree1.commit("upstream one")
1704
        self.db1.tag_upstream_version(version1)
1705
        self.up_tree2.pull(self.up_tree1.branch)
1706
        self.db2.tag_upstream_version(version2)
1707
        up_revid2 = self.up_tree1.commit("upstream two")
1708
        self.db1.tag_upstream_version(version3)
1709
        self.up_tree2.pull(self.up_tree1.branch)
1710
        self.db2.tag_upstream_version(version4)
1711
        versions = [version4, version3, version2, version1]
1712
        # no upstream parent as the lesser branch has already merged it
1713
        self.assertEqual(self.db2.get_parents_with_upstream(version4,
1714
                    versions), [revid2, revid3])
1715
1716
    def test_get_parents_with_upstream_force_upstream(self):
1717
        version1 = Version("0.1-1")
1718
        version2 = Version("0.1-1ubuntu1")
1719
        revid1 = self.tree1.commit("one")
1720
        self.db1.tag_version(version1)
1721
        up_revid1 = self.up_tree1.commit("upstream one")
1722
        self.db1.tag_upstream_version(version1)
1723
        up_revid2 = self.up_tree2.commit("different upstream one")
1724
        self.db2.tag_upstream_version(version2)
1725
        versions = [version2, version1]
1726
        # a previous test checked that this wouldn't give an
1727
        # upstream parent, but we are requiring one.
1728
        self.assertEqual(self.db2.get_parents_with_upstream(version2,
1729
                    versions, force_upstream_parent=True),
1730
                [revid1, up_revid2])
1731
1732
    def test_get_parents_with_upstream_sync_when_diverged(self):
1733
        version1 = Version("0.1-1")
1734
        version2 = Version("0.1-1ubuntu1")
1735
        version3 = Version("0.1-2")
1736
        revid1 = self.tree1.commit("one")
1737
        revid2 = self.tree2.commit("two")
1738
        revid3 = self.tree1.commit("three")
1739
        self.db1.tag_version(version1)
1740
        self.db2.tag_version(version2)
1741
        self.db1.tag_version(version3)
1742
        up_revid1 = self.up_tree1.commit("upstream one")
1743
        self.db1.tag_upstream_version(version1)
1744
        self.up_tree2.pull(self.up_tree1.branch)
1745
        self.db2.tag_upstream_version(version2)
1746
        versions = [version3, version2, version1]
1747
        # This is a sync but we are diverged so we should get two
1748
        # parents
1749
        self.assertEqual(self.db2.get_parents_with_upstream(version3,
1750
                    versions), [revid2, revid3])
1751
1752
    def test_get_parents_with_upstream_sync_new_upstream(self):
1753
        version1 = Version("0.1-1")
1754
        version2 = Version("0.1-1ubuntu1")
1755
        version3 = Version("0.2-1")
1756
        revid1 = self.tree1.commit("one")
1757
        revid2 = self.tree2.commit("two")
1758
        revid3 = self.tree1.commit("three")
1759
        self.db1.tag_version(version1)
1760
        self.db2.tag_version(version2)
1761
        self.db1.tag_version(version3)
1762
        up_revid1 = self.up_tree1.commit("upstream one")
1763
        self.db1.tag_upstream_version(version1)
1764
        self.up_tree2.pull(self.up_tree1.branch)
1765
        self.db2.tag_upstream_version(version2)
1766
        up_revid2 = self.up_tree1.commit("upstream two")
1767
        self.db1.tag_upstream_version(version3)
1768
        versions = [version3, version2, version1]
1769
        # This a sync, but we are diverged, so we should get two
1770
        # parents. There should be no upstream as the synced
1771
        # version will already have it.
1772
        self.assertEqual(self.db2.get_parents_with_upstream(version3,
1773
                    versions), [revid2, revid3])
1774
1775
    def test_get_parents_with_upstream_sync_new_upstream_force(self):
1776
        version1 = Version("0.1-1")
1777
        version2 = Version("0.1-1ubuntu1")
1778
        version3 = Version("0.2-1")
1779
        revid1 = self.tree1.commit("one")
1780
        revid2 = self.tree2.commit("two")
1781
        revid3 = self.tree1.commit("three")
1782
        self.db1.tag_version(version1)
1783
        self.db2.tag_version(version2)
1784
        self.db1.tag_version(version3)
1785
        up_revid1 = self.up_tree1.commit("upstream one")
1786
        self.db1.tag_upstream_version(version1)
1787
        self.up_tree2.pull(self.up_tree1.branch)
1788
        self.db2.tag_upstream_version(version2)
1789
        up_revid2 = self.up_tree1.commit("upstream two")
1790
        self.db1.tag_upstream_version(version3)
1791
        versions = [version3, version2, version1]
1792
        up_revid3 = self.up_tree2.commit("different upstream two")
1793
        self.db2.tag_upstream_version(version3)
1794
        versions = [version3, version2, version1]
1795
        # test_get_parents_with_upstream_sync_new_upstream
1796
        # checks that there is not normally an upstream parent
1797
        # when we fake-sync, but we are forcing one here.
1798
        #TODO: should the upstream parent be second or third?
1799
        self.assertEqual(self.db2.get_parents_with_upstream(version3,
1800
                    versions, force_upstream_parent=True),
1801
                [revid2, up_revid3, revid3])
1802
1803
    def test_branch_to_pull_version_from(self):
1804
        """Test the check for pulling from a branch.
1805
1806
        It should only return a branch to pull from if the version
1807
        is present with the correct md5, and the history has not
1808
        diverged.
1809
        """
1810
        version1 = Version("0.1-1")
1811
        version2 = Version("0.1-1ubuntu1")
1812
        # With no versions tagged everything is None
1813
        branch = self.db2.branch_to_pull_version_from(version1,
1814
                self.fake_md5_1)
1815
        self.assertEqual(branch, None)
1816
        branch = self.db2.branch_to_pull_version_from(version1,
1817
                self.fake_md5_2)
1818
        self.assertEqual(branch, None)
1819
        branch = self.db1.branch_to_pull_version_from(version1,
1820
                self.fake_md5_1)
1821
        self.assertEqual(branch, None)
1822
        # Version and md5 available, so we get the correct branch.
1823
        self.do_commit_with_md5(self.tree1, "one", self.fake_md5_1)
1824
        self.db1.tag_version(version1)
1825
        branch = self.db2.branch_to_pull_version_from(version1,
1826
                self.fake_md5_1)
1827
        self.assertEqual(branch, self.db1)
1828
        # Otherwise (different version or md5) then we get None
1829
        branch = self.db2.branch_to_pull_version_from(version1,
1830
                self.fake_md5_2)
1831
        self.assertEqual(branch, None)
1832
        branch = self.db2.branch_to_pull_version_from(version2,
1833
                self.fake_md5_1)
1834
        self.assertEqual(branch, None)
1835
        branch = self.db2.branch_to_pull_version_from(version2,
1836
                self.fake_md5_2)
1837
        self.assertEqual(branch, None)
1838
        # And we still don't get a branch for the one that already
1839
        # has the version
1840
        branch = self.db1.branch_to_pull_version_from(version1,
1841
                self.fake_md5_1)
1842
        self.assertEqual(branch, None)
1843
        # And we get the greatest branch when two lesser branches
1844
        # have what we are looking for.
1845
        self.tree2.pull(self.tree1.branch)
1846
        self.db2.tag_version(version1)
1847
        branch = self.db3.branch_to_pull_version_from(version1,
1848
                self.fake_md5_1)
1849
        self.assertEqual(branch, self.db2)
1850
        # If the branches have diverged then we don't get a branch.
1851
        self.tree3.commit("three")
1852
        branch = self.db3.branch_to_pull_version_from(version1,
1853
                self.fake_md5_1)
1854
        self.assertEqual(branch, None)
1855
1856
    def test_branch_to_pull_upstream_from(self):
1857
        version1 = Version("0.1-1")
1858
        version2 = Version("0.2-1")
1859
        # With no versions tagged everything is None
1860
        branch = self.db2.branch_to_pull_upstream_from(version1,
1861
                self.fake_md5_1)
1862
        self.assertEqual(branch, None)
1863
        branch = self.db2.branch_to_pull_upstream_from(version1,
1864
                self.fake_md5_2)
1865
        self.assertEqual(branch, None)
1866
        branch = self.db1.branch_to_pull_upstream_from(version1,
1867
                self.fake_md5_1)
1868
        self.assertEqual(branch, None)
1869
        self.do_commit_with_md5(self.up_tree1, "one", self.fake_md5_1)
1870
        self.db1.tag_upstream_version(version1)
1871
        # Version and md5 available, so we get the correct branch.
1872
        branch = self.db2.branch_to_pull_upstream_from(version1,
1873
                self.fake_md5_1)
1874
        self.assertEqual(branch, self.db1)
1875
        # Otherwise (different version or md5) then we get None
1876
        branch = self.db2.branch_to_pull_upstream_from(version1,
1877
                self.fake_md5_2)
1878
        self.assertEqual(branch, None)
1879
        branch = self.db2.branch_to_pull_upstream_from(version2,
1880
                self.fake_md5_1)
1881
        self.assertEqual(branch, None)
1882
        branch = self.db2.branch_to_pull_upstream_from(version2,
1883
                self.fake_md5_2)
1884
        self.assertEqual(branch, None)
1885
        # And we don't get a branch for the one that already has
1886
        # the version
1887
        branch = self.db1.branch_to_pull_upstream_from(version1,
1888
                self.fake_md5_1)
1889
        self.assertEqual(branch, None)
1890
        self.up_tree2.pull(self.up_tree1.branch)
1891
        self.db2.tag_upstream_version(version1)
1892
        # And we get the greatest branch when two lesser branches
1893
        # have what we are looking for.
1894
        branch = self.db3.branch_to_pull_upstream_from(version1,
1895
                self.fake_md5_1)
1896
        self.assertEqual(branch, self.db2)
1897
        # If the branches have diverged then we don't get a branch.
1898
        self.up_tree3.commit("three")
1899
        branch = self.db3.branch_to_pull_upstream_from(version1,
1900
                self.fake_md5_1)
1901
        self.assertEqual(branch, None)
1902
1903
    def test_pull_from_lesser_branch_no_upstream(self):
1904
        version = Version("0.1-1")
1905
        self.do_commit_with_md5(self.up_tree1, "upstream one",
1906
                self.fake_md5_1)
1907
        self.db1.tag_upstream_version(version)
1908
        up_revid = self.do_commit_with_md5(self.up_tree2, "upstream two",
1909
                self.fake_md5_1)
1910
        self.db2.tag_upstream_version(version)
1911
        revid = self.do_commit_with_md5(self.tree1, "one", self.fake_md5_2)
1912
        self.db1.tag_version(version)
1913
        self.assertNotEqual(self.tree2.branch.last_revision(), revid)
1914
        self.db2.pull_version_from_branch(self.db1, version)
1915
        self.assertEqual(self.tree2.branch.last_revision(), revid)
1916
        self.assertEqual(self.up_tree2.branch.last_revision(), up_revid)
1917
        self.assertEqual(self.db2.revid_of_version(version), revid)
1918
        self.assertEqual(self.db2.revid_of_upstream_version(version),
1919
                up_revid)
1920
1921
    def test_pull_from_lesser_branch_with_upstream(self):
1922
        version = Version("0.1-1")
1923
        up_revid = self.do_commit_with_md5(self.up_tree1, "upstream one",
1924
                self.fake_md5_1)
1925
        self.db1.tag_upstream_version(version)
1926
        revid = self.do_commit_with_md5(self.tree1, "one", self.fake_md5_2)
1927
        self.db1.tag_version(version)
1928
        self.assertNotEqual(self.tree2.branch.last_revision(), revid)
1929
        self.assertNotEqual(self.up_tree2.branch.last_revision(), up_revid)
1930
        self.db2.pull_version_from_branch(self.db1, version)
1931
        self.assertEqual(self.tree2.branch.last_revision(), revid)
1932
        self.assertEqual(self.up_tree2.branch.last_revision(), up_revid)
1933
        self.assertEqual(self.db2.revid_of_version(version), revid)
1934
        self.assertEqual(self.db2.revid_of_upstream_version(version),
1935
                up_revid)
1936
1937
    def test_pull_upstream_from_branch(self):
1938
        version = Version("0.1-1")
1939
        up_revid = self.do_commit_with_md5(self.up_tree1, "upstream one",
1940
                self.fake_md5_1)
1941
        self.db1.tag_upstream_version(version)
1942
        self.assertNotEqual(self.up_tree2.branch.last_revision(), up_revid)
1943
        self.db2.pull_upstream_from_branch(self.db1, version)
1944
        self.assertEqual(self.up_tree2.branch.last_revision(), up_revid)
1945
        self.assertEqual(self.db2.revid_of_upstream_version(version),
1946
                up_revid)
1947
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
1948
    def test_extract_dsc(self):
1949
        version = Version("0.1-1")
1950
        name = "package"
1951
        builder = SourcePackageBuilder(name, version)
1952
        builder.add_upstream_file("README", "Hi\n")
1953
        builder.add_upstream_file("BUGS")
1954
        builder.add_default_control()
1955
        builder.build()
1956
        tempdir = self.db1.extract_dsc(builder.dsc_name())
1957
        self.assertTrue(os.path.exists(tempdir))
1958
        try:
1959
            unpacked_dir = os.path.join(tempdir,
1960
                            name+"-"+str(version.upstream_version))
1961
            orig_dir = unpacked_dir + ".orig"
1962
            self.assertTrue(os.path.exists(unpacked_dir))
1963
            self.assertTrue(os.path.exists(orig_dir))
1964
            self.assertTrue(os.path.exists(os.path.join(unpacked_dir,
1965
                            "README")))
1966
            self.assertTrue(os.path.exists(os.path.join(unpacked_dir,
1967
                            "debian", "control")))
1968
            self.assertTrue(os.path.exists(os.path.join(orig_dir,
1969
                            "README")))
1970
            self.assertFalse(os.path.exists(os.path.join(orig_dir,
1971
                            "debian", "control")))
1972
        finally:
1973
            shutil.rmtree(tempdir)
1974
229 by James Westby
Use file ids from other trees.
1975
    def check_changes(self, changes, added=[], removed=[], modified=[],
1976
                      renamed=[]):
1977
        def check_one_type(type, expected, actual):
1978
            def make_set(list):
1979
                output = set()
1980
                for item in list:
1981
                    if item[2] == 'directory':
1982
                        output.add(item[0] + '/')
1983
                    else:
1984
                        output.add(item[0])
1985
                return output
1986
            exp = set(expected)
1987
            real = make_set(actual)
1988
            missing = exp.difference(real)
1989
            extra = real.difference(exp)
1990
            if len(missing) > 0:
1991
                self.fail("Some expected paths not found %s in the changes: "
1992
                          "%s, expected %s, got %s." % (type, str(missing),
1993
                              str(expected), str(actual)))
1994
            if len(extra) > 0:
1995
                self.fail("Some extra paths found %s in the changes: "
1996
                          "%s, expected %s, got %s." % (type, str(extra),
1997
                              str(expected), str(actual)))
1998
        check_one_type("added", added, changes.added)
1999
        check_one_type("removed", removed, changes.removed)
2000
        check_one_type("modified", modified, changes.modified)
2001
        check_one_type("renamed", renamed, changes.renamed)
2002
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2003
    def test_import_upstream(self):
2004
        version = Version("0.1-1")
2005
        name = "package"
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
2006
        basedir = name + "-" + str(version.upstream_version)
2007
        os.mkdir(basedir)
2008
        write_to_file(os.path.join(basedir, "README"), "Hi\n")
2009
        write_to_file(os.path.join(basedir, "BUGS"), "")
235.1.2 by James Westby
Handle more transitions between native and non-native.
2010
        self.db1.import_upstream(basedir, version, self.fake_md5_1, [])
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2011
        tree = self.up_tree1
2012
        branch = tree.branch
2013
        rh = branch.revision_history()
2014
        self.assertEqual(len(rh), 1)
2015
        self.assertEqual(self.db1.revid_of_upstream_version(version), rh[0])
2016
        rev = branch.repository.get_revision(rh[0])
2017
        self.assertEqual(rev.message,
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
2018
                "Import upstream version %s" % str(version.upstream_version))
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2019
        self.assertEqual(rev.properties['deb-md5'], self.fake_md5_1)
2020
229 by James Westby
Use file ids from other trees.
2021
    def test_import_upstream_on_another(self):
2022
        version1 = Version("0.1-1")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2023
        version2 = Version("0.2-1")
229 by James Westby
Use file ids from other trees.
2024
        name = "package"
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
2025
        basedir = name + "-" + str(version1.upstream_version)
2026
        os.mkdir(basedir)
2027
        write_to_file(os.path.join(basedir, "README"), "Hi\n")
2028
        write_to_file(os.path.join(basedir, "BUGS"), "")
2029
        write_to_file(os.path.join(basedir, "COPYING"), "")
235.1.2 by James Westby
Handle more transitions between native and non-native.
2030
        self.db1.import_upstream(basedir, version1, self.fake_md5_1, [])
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
2031
        basedir = name + "-" + str(version2.upstream_version)
2032
        os.mkdir(basedir)
2033
        write_to_file(os.path.join(basedir, "README"), "Now even better\n")
2034
        write_to_file(os.path.join(basedir, "BUGS"), "")
2035
        write_to_file(os.path.join(basedir, "NEWS"), "")
235.1.2 by James Westby
Handle more transitions between native and non-native.
2036
        self.db1.import_upstream(basedir, version2, self.fake_md5_2,
2037
                [self.up_tree1.branch.last_revision()])
229 by James Westby
Use file ids from other trees.
2038
        tree = self.up_tree1
2039
        branch = tree.branch
2040
        rh = branch.revision_history()
2041
        self.assertEqual(len(rh), 2)
2042
        self.assertEqual(self.db1.revid_of_upstream_version(version2), rh[1])
2043
        rev = branch.repository.get_revision(rh[1])
2044
        self.assertEqual(rev.message,
232 by James Westby
Use dpkg-source to extract the source packages and then import from that.
2045
                "Import upstream version %s" % str(version2.upstream_version))
229 by James Westby
Use file ids from other trees.
2046
        self.assertEqual(rev.properties['deb-md5'], self.fake_md5_2)
2047
        rev_tree1 = branch.repository.revision_tree(rh[0])
2048
        rev_tree2 = branch.repository.revision_tree(rh[1])
2049
        changes = rev_tree2.changes_from(rev_tree1)
2050
        self.check_changes(changes, added=["NEWS"], removed=["COPYING"],
2051
                modified=["README"])
2052
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2053
    def test_import_package_init_from_other(self):
2054
        version1 = Version("0.1-1")
2055
        version2 = Version("0.2-1")
233 by James Westby
Make the SourcePackageBuilder easier to use.
2056
        builder = SourcePackageBuilder("package", version1)
240 by James Westby
Fix starting an upstream branch from another.
2057
        builder.add_default_control()
2058
        builder.build()
2059
        self.db1.import_package(builder.dsc_name())
2060
        self.db1.upstream_tree = None
233 by James Westby
Make the SourcePackageBuilder easier to use.
2061
        builder.new_version(version2)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2062
        builder.build()
2063
        self.db2.import_package(builder.dsc_name())
2064
        self.assertEqual(len(self.up_tree2.branch.revision_history()), 2)
229 by James Westby
Use file ids from other trees.
2065
        self.assertEqual(len(self.tree2.branch.revision_history()), 3)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2066
2067
    def import_package_single(self):
2068
        version1 = Version("0.1-1")
2069
        builder = SourcePackageBuilder("package", version1)
2070
        builder.add_upstream_file("README", "foo")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2071
        builder.add_default_control()
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2072
        builder.build()
2073
        self.db1.import_package(builder.dsc_name())
229 by James Westby
Use file ids from other trees.
2074
        self.assertEqual(len(self.up_tree1.branch.revision_history()), 1)
2075
        self.assertEqual(len(self.tree1.branch.revision_history()), 2)
2076
2077
    def test_import_package_double(self):
2078
        version1 = Version("0.1-1")
2079
        version2 = Version("0.2-1")
2080
        builder = SourcePackageBuilder("package", version1)
2081
        builder.add_upstream_file("README", "foo")
2082
        builder.add_upstream_file("BUGS")
2083
        builder.add_upstream_file("NEWS")
2084
        builder.add_debian_file("COPYING", "Don't do it\n")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2085
        builder.add_default_control()
229 by James Westby
Use file ids from other trees.
2086
        builder.build()
2087
        self.db1.import_package(builder.dsc_name())
233 by James Westby
Make the SourcePackageBuilder easier to use.
2088
        builder.new_version(version2)
229 by James Westby
Use file ids from other trees.
2089
        builder.add_upstream_file("README", "bar")
2090
        builder.add_upstream_file("COPYING", "Please do\n")
2091
        builder.add_upstream_file("src.c")
233 by James Westby
Make the SourcePackageBuilder easier to use.
2092
        builder.remove_upstream_file("NEWS")
2093
        builder.remove_debian_file("COPYING")
229 by James Westby
Use file ids from other trees.
2094
        builder.build()
2095
        self.db1.import_package(builder.dsc_name())
2096
        rh = self.tree1.branch.revision_history()
2097
        up_rh = self.up_tree1.branch.revision_history()
2098
        self.assertEqual(len(up_rh), 2)
2099
        self.assertEqual(len(rh), 3)
2100
        self.assertEqual(rh[0], up_rh[0])
2101
        self.assertNotEqual(rh[1], up_rh[1])
2102
        # Check the parents are correct.
2103
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh[1])
2104
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh[2])
2105
        up_rev_tree1 = self.up_tree1.branch.repository.revision_tree(up_rh[0])
2106
        up_rev_tree2 = self.up_tree1.branch.repository.revision_tree(up_rh[1])
2107
        self.assertEqual(up_rev_tree1.get_parent_ids(), [])
2108
        self.assertEqual(up_rev_tree2.get_parent_ids(), [up_rh[0]])
2109
        self.assertEqual(rev_tree1.get_parent_ids(), [up_rh[0]])
2110
        self.assertEqual(rev_tree2.get_parent_ids(), [rh[1], up_rh[1]])
2111
        # Check that the file ids are correct.
2112
        self.check_changes(up_rev_tree2.changes_from(up_rev_tree1),
2113
                added=["COPYING", "src.c"], removed=["NEWS"],
2114
                modified=["README"])
2115
        self.check_changes(rev_tree1.changes_from(up_rev_tree1),
231 by James Westby
Use dpkg-source to build the source packages for testing.
2116
                added=["debian/", "debian/changelog", "COPYING",
2117
                "debian/control"])
229 by James Westby
Use file ids from other trees.
2118
        self.check_changes(rev_tree2.changes_from(rev_tree1),
2119
                modified=["debian/changelog", "COPYING", "README"],
2120
                added=["src.c"], removed=["NEWS"])
2121
        self.check_changes(rev_tree2.changes_from(up_rev_tree2),
231 by James Westby
Use dpkg-source to build the source packages for testing.
2122
                added=["debian/", "debian/changelog", "debian/control"])
229 by James Westby
Use file ids from other trees.
2123
        self.check_changes(up_rev_tree2.changes_from(rev_tree1),
2124
                added=["src.c"],
231 by James Westby
Use dpkg-source to build the source packages for testing.
2125
                removed=["NEWS", "debian/", "debian/changelog",
2126
                "debian/control"],
229 by James Westby
Use file ids from other trees.
2127
                modified=["README", "COPYING"])
2128
2129
    def test_import_two_roots(self):
2130
        version1 = Version("0.1-0ubuntu1")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2131
        version2 = Version("0.2-1")
229 by James Westby
Use file ids from other trees.
2132
        builder = SourcePackageBuilder("package", version1)
2133
        builder.add_upstream_file("README", "foo")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2134
        builder.add_default_control()
229 by James Westby
Use file ids from other trees.
2135
        builder.build()
2136
        self.db2.import_package(builder.dsc_name())
2137
        builder = SourcePackageBuilder("package", version2)
2138
        builder.add_upstream_file("README", "bar")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2139
        builder.add_default_control()
229 by James Westby
Use file ids from other trees.
2140
        builder.build()
2141
        self.db1.import_package(builder.dsc_name())
2142
        rh1 = self.tree1.branch.revision_history()
2143
        rh2 = self.tree2.branch.revision_history()
2144
        up_rh1 = self.up_tree1.branch.revision_history()
2145
        up_rh2 = self.up_tree2.branch.revision_history()
2146
        self.assertEqual(len(rh1), 2)
2147
        self.assertEqual(len(rh2), 2)
2148
        self.assertEqual(len(up_rh1), 1)
2149
        self.assertEqual(len(up_rh2), 1)
2150
        self.assertNotEqual(rh1, rh2)
2151
        self.assertNotEqual(rh1[0], rh2[0])
2152
        self.assertNotEqual(rh1[1], rh2[1])
2153
        self.assertEqual(rh1[0], up_rh1[0])
2154
        self.assertEqual(rh2[0], up_rh2[0])
2155
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
2156
        rev_tree2 = self.tree2.branch.repository.revision_tree(rh2[1])
2157
        up_rev_tree1 = self.up_tree1.branch.repository.revision_tree(rh1[0])
2158
        up_rev_tree2 = self.up_tree2.branch.repository.revision_tree(rh2[0])
2159
        self.check_changes(rev_tree1.changes_from(up_rev_tree1),
231 by James Westby
Use dpkg-source to build the source packages for testing.
2160
                added=["debian/", "debian/changelog", "debian/control"])
229 by James Westby
Use file ids from other trees.
2161
        self.check_changes(rev_tree2.changes_from(up_rev_tree2),
231 by James Westby
Use dpkg-source to build the source packages for testing.
2162
                added=["debian/", "debian/changelog", "debian/control"])
229 by James Westby
Use file ids from other trees.
2163
        self.check_changes(rev_tree2.changes_from(rev_tree1),
2164
                modified=["README", "debian/changelog"])
2165
        self.check_changes(up_rev_tree2.changes_from(up_rev_tree1),
2166
                modified=["README"])
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2167
237 by James Westby
Don't override the tip of a branch when importing.
2168
    def test_sync_to_other_branch(self):
2169
        version1 = Version("0.1-1")
2170
        version2 = Version("0.1-1ubuntu1")
2171
        version3 = Version("0.2-1")
2172
        builder = SourcePackageBuilder("package", version1)
2173
        builder.add_upstream_file("README", "foo")
2174
        builder.add_default_control()
2175
        builder.build()
2176
        self.db1.import_package(builder.dsc_name())
2177
        self.db2.import_package(builder.dsc_name())
2178
        builder.new_version(version2)
2179
        builder.add_upstream_file("README", "bar")
2180
        builder.add_default_control()
2181
        builder.build()
2182
        self.db2.import_package(builder.dsc_name())
2183
        builder = SourcePackageBuilder("package", version1)
2184
        builder.new_version(version3)
2185
        builder.add_upstream_file("README", "baz")
2186
        builder.add_default_control()
2187
        builder.build()
2188
        self.db1.import_package(builder.dsc_name())
2189
        self.db2.import_package(builder.dsc_name())
2190
        rh1 = self.tree1.branch.revision_history()
2191
        rh2 = self.tree2.branch.revision_history()
2192
        up_rh1 = self.up_tree1.branch.revision_history()
2193
        up_rh2 = self.up_tree2.branch.revision_history()
2194
        self.assertEqual(len(rh1), 3)
2195
        self.assertEqual(len(rh2), 4)
2196
        self.assertEqual(len(up_rh1), 2)
2197
        self.assertEqual(len(up_rh2), 2)
2198
        self.assertEqual(rh1[0], up_rh1[0])
2199
        self.assertEqual(rh2[0], up_rh2[0])
2200
        self.assertEqual(rh1[0], rh2[0])
2201
        self.assertEqual(rh1[1], rh2[1])
2202
        self.assertNotEqual(rh1[2], rh2[2])
2203
        self.assertEqual(up_rh1[1], up_rh2[1])
2204
        rev_tree1 = self.tree2.branch.repository.revision_tree(rh2[2])
2205
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[2])
2206
        rev_tree3 = self.tree2.branch.repository.revision_tree(rh2[3])
2207
        self.assertEqual(rev_tree1.get_parent_ids(), [rh2[1]])
2208
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[1], up_rh1[1]])
2209
        self.assertEqual(rev_tree3.get_parent_ids(), [rh2[2], rh1[2]])
2210
        self.check_changes(rev_tree2.changes_from(rev_tree1),
2211
                modified=["README", "debian/changelog"])
2212
        self.check_changes(rev_tree3.changes_from(rev_tree2))
2213
        self.check_changes(rev_tree3.changes_from(rev_tree1),
2214
                modified=["README", "debian/changelog"])
2215
241 by James Westby
Add an XFAIL test for importing parallel branches.
2216
    def test_pull_from_other(self):
2217
        version1 = Version("0.1-1")
2218
        version2 = Version("0.2-1")
2219
        version3 = Version("0.3-1")
2220
        builder = SourcePackageBuilder("package", version1)
2221
        builder.add_default_control()
2222
        builder.build()
2223
        self.db1.import_package(builder.dsc_name())
2224
        self.db2.import_package(builder.dsc_name())
2225
        builder.new_version(version2)
2226
        builder.build()
2227
        self.db2.import_package(builder.dsc_name())
2228
        builder.new_version(version3)
2229
        builder.build()
2230
        self.db1.import_package(builder.dsc_name())
2231
        try:
2232
            self.db2.import_package(builder.dsc_name())
2233
        except DivergedBranches:
2234
            raise KnownFailure("Pulling from another branch after "
2235
                    "merge the other way fails due to assuming the "
2236
                    "upstream branch can be pulled too, but we never "
2237
                    "merge upstream branches.")
2238
235 by James Westby
Add support for importing native packages.
2239
    def test_is_native_version(self):
2240
        version1 = Version("0.1-0ubuntu1")
2241
        version2 = Version("0.2-1")
2242
        self.tree1.commit("one")
2243
        self.db1.tag_version(version1)
2244
        self.tree1.commit("two", revprops={'deb-native': "True"})
2245
        self.db1.tag_version(version2)
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2246
        self.tree1.lock_read()
2247
        self.addCleanup(self.tree1.unlock)
235 by James Westby
Add support for importing native packages.
2248
        self.assertFalse(self.db1.is_version_native(version1))
2249
        self.assertTrue(self.db1.is_version_native(version2))
2250
234 by James Westby
Support basic importing of native packages.
2251
    def test_import_native(self):
2252
        version = Version("1.0")
2253
        builder = SourcePackageBuilder("package", version, native=True)
2254
        builder.add_default_control()
2255
        builder.build()
2256
        self.db1.import_package(builder.dsc_name())
2257
        rh1 = self.tree1.branch.revision_history()
2258
        up_rh1 = self.up_tree1.branch.revision_history()
2259
        self.assertEqual(len(rh1), 1)
2260
        self.assertEqual(len(up_rh1), 0)
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2261
        self.tree1.lock_read()
2262
        self.addCleanup(self.tree1.unlock)
235 by James Westby
Add support for importing native packages.
2263
        self.assertTrue(self.db1.is_version_native(version))
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2264
        revtree = self.tree1.branch.repository.revision_tree(rh1[0])
2265
        self.assertTrue(self.db1._is_tree_native(revtree))
234 by James Westby
Support basic importing of native packages.
2266
2267
    def test_import_native_two(self):
2268
        version1 = Version("1.0")
2269
        version2 = Version("1.1")
2270
        builder = SourcePackageBuilder("package", version1, native=True)
2271
        builder.add_debian_file("COPYING", "don't do it\n")
2272
        builder.add_debian_file("README")
2273
        builder.add_default_control()
2274
        builder.build()
2275
        self.db1.import_package(builder.dsc_name())
2276
        builder.new_version(version2)
2277
        builder.remove_debian_file("README")
2278
        builder.add_debian_file("COPYING", "do it\n")
2279
        builder.add_debian_file("NEWS")
2280
        builder.build()
2281
        self.db1.import_package(builder.dsc_name())
2282
        rh1 = self.tree1.branch.revision_history()
2283
        up_rh1 = self.up_tree1.branch.revision_history()
2284
        self.assertEqual(len(rh1), 2)
2285
        self.assertEqual(len(up_rh1), 0)
2286
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[0])
2287
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[1])
2288
        self.assertEqual(rev_tree1.get_parent_ids(), [])
2289
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[0]])
2290
        self.check_changes(rev_tree2.changes_from(rev_tree1),
2291
                added=["NEWS"], removed=["README"],
2292
                modified=["debian/changelog", "COPYING"])
2293
        self.assertEqual(self.db1.revid_of_version(version1), rh1[0])
2294
        self.assertEqual(self.db1.revid_of_version(version2), rh1[1])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2295
        self.tree1.lock_read()
2296
        self.addCleanup(self.tree1.unlock)
235 by James Westby
Add support for importing native packages.
2297
        self.assertTrue(self.db1.is_version_native(version1))
2298
        self.assertTrue(self.db1.is_version_native(version2))
234 by James Westby
Support basic importing of native packages.
2299
242 by James Westby
Don't try and commit with no parents if it's not the initial commit.
2300
    def test_import_native_two_unrelated(self):
2301
        version1 = Version("1.0")
2302
        version2 = Version("1.1")
2303
        builder = SourcePackageBuilder("package", version1, native=True)
2304
        builder.add_default_control()
2305
        builder.add_upstream_file("README", "foo")
2306
        builder.build()
2307
        self.db1.import_package(builder.dsc_name())
2308
        builder = SourcePackageBuilder("package", version2, native=True)
2309
        builder.add_default_control()
2310
        builder.add_upstream_file("README", "bar")
2311
        builder.build()
2312
        self.db1.import_package(builder.dsc_name())
2313
        rh1 = self.tree1.branch.revision_history()
2314
        up_rh1 = self.up_tree1.branch.revision_history()
2315
        self.assertEqual(len(rh1), 2)
2316
        self.assertEqual(len(up_rh1), 0)
2317
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[0])
2318
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[1])
2319
        self.assertEqual(rev_tree1.get_parent_ids(), [])
2320
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[0]])
2321
        self.check_changes(rev_tree2.changes_from(rev_tree1),
2322
                modified=["README", "debian/changelog"])
2323
        self.assertEqual(self.db1.revid_of_version(version1), rh1[0])
2324
        self.assertEqual(self.db1.revid_of_version(version2), rh1[1])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2325
        self.tree1.lock_read()
2326
        self.addCleanup(self.tree1.unlock)
242 by James Westby
Don't try and commit with no parents if it's not the initial commit.
2327
        self.assertTrue(self.db1.is_version_native(version1))
2328
        self.assertTrue(self.db1.is_version_native(version2))
2329
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2330
    def test_import_non_native_to_native(self):
2331
        version1 = Version("1.0-1")
2332
        version2 = Version("1.0-2")
2333
        builder = SourcePackageBuilder("package", version1)
2334
        builder.add_upstream_file("COPYING", "don't do it\n")
2335
        builder.add_upstream_file("BUGS")
2336
        builder.add_debian_file("README", "\n")
2337
        builder.add_default_control()
2338
        builder.build()
2339
        self.db1.import_package(builder.dsc_name())
2340
        builder.native = True
2341
        builder.new_version(version2)
2342
        builder.remove_upstream_file("BUGS")
2343
        builder.add_upstream_file("COPYING", "do it\n")
2344
        builder.add_upstream_file("NEWS")
2345
        builder.build()
2346
        self.db1.import_package(builder.dsc_name())
2347
        rh1 = self.tree1.branch.revision_history()
2348
        up_rh1 = self.up_tree1.branch.revision_history()
2349
        self.assertEqual(len(rh1), 3)
2350
        self.assertEqual(len(up_rh1), 1)
2351
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
2352
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[2])
2353
        self.assertEqual(rev_tree1.get_parent_ids(), [rh1[0]])
2354
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[1]])
2355
        self.check_changes(rev_tree2.changes_from(rev_tree1),
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2356
                added=["NEWS", ".bzr-builddeb/",
2357
                    ".bzr-builddeb/default.conf"],
2358
                removed=["BUGS"], modified=["debian/changelog", "COPYING"])
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2359
        self.assertEqual(self.db1.revid_of_version(version1), rh1[1])
2360
        self.assertEqual(self.db1.revid_of_version(version2), rh1[2])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2361
        self.tree1.lock_read()
2362
        self.addCleanup(self.tree1.unlock)
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2363
        self.assertFalse(self.db1.is_version_native(version1))
2364
        self.assertTrue(self.db1.is_version_native(version2))
2365
2366
    def test_import_native_to_non_native(self):
2367
        version1 = Version("1.0")
2368
        version2 = Version("1.1-1")
2369
        builder = SourcePackageBuilder("package", version1, native=True)
2370
        builder.add_upstream_file("COPYING", "don't do it\n")
2371
        builder.add_upstream_file("BUGS")
2372
        builder.add_debian_file("README", "\n")
2373
        builder.add_default_control()
2374
        builder.build()
2375
        self.db1.import_package(builder.dsc_name())
2376
        builder.native = False
2377
        builder.new_version(version2)
2378
        builder.remove_upstream_file("BUGS")
2379
        builder.add_upstream_file("COPYING", "do it\n")
2380
        builder.add_upstream_file("NEWS")
2381
        builder.build()
2382
        self.db1.import_package(builder.dsc_name())
2383
        rh1 = self.tree1.branch.revision_history()
2384
        up_rh1 = self.up_tree1.branch.revision_history()
2385
        self.assertEqual(len(rh1), 2)
2386
        self.assertEqual(len(up_rh1), 2)
2387
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[0])
2388
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[1])
2389
        up_rev_tree1 = \
2390
                self.up_tree1.branch.repository.revision_tree(up_rh1[1])
2391
        self.assertEqual(rev_tree1.get_parent_ids(), [])
2392
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[0], up_rh1[1]])
2393
        self.assertEqual(up_rev_tree1.get_parent_ids(), [rh1[0]])
2394
        self.check_changes(rev_tree2.changes_from(rev_tree1),
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2395
                added=["NEWS"],
2396
                removed=["BUGS", ".bzr-builddeb/",
2397
                    ".bzr-builddeb/default.conf"],
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2398
                modified=["debian/changelog", "COPYING"])
2399
        self.check_changes(up_rev_tree1.changes_from(rev_tree1),
2400
                added=["NEWS"],
2401
                removed=["debian/", "debian/changelog", "debian/control",
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2402
                        "BUGS", "README", ".bzr-builddeb/",
2403
                        ".bzr-builddeb/default.conf"],
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2404
                modified=["COPYING"])
2405
        self.check_changes(rev_tree2.changes_from(up_rev_tree1),
2406
                added=["debian/", "debian/changelog", "debian/control",
2407
                "README"])
2408
        self.assertEqual(self.db1.revid_of_version(version1), rh1[0])
2409
        self.assertEqual(self.db1.revid_of_version(version2), rh1[1])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2410
        self.tree1.lock_read()
2411
        self.addCleanup(self.tree1.unlock)
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2412
        self.assertTrue(self.db1.is_version_native(version1))
2413
        self.assertFalse(self.db1.is_version_native(version2))
2414
235.1.2 by James Westby
Handle more transitions between native and non-native.
2415
    def test_import_to_native_and_back_same_upstream(self):
2416
        """Non-native to native and back all in the same upstream version.
2417
2418
        As the native version was on the same upstream as a non-native
2419
        version we assume that it was accidental, and so don't include
2420
        the native revision in the upstream branch's history.
2421
        """
2422
        version1 = Version("1.0-1")
2423
        version2 = Version("1.0-2")
2424
        version3 = Version("1.0-3")
2425
        builder = SourcePackageBuilder("package", version1)
2426
        builder.add_default_control()
2427
        builder.build()
2428
        self.db1.import_package(builder.dsc_name())
2429
        builder.native = True
2430
        builder.new_version(version2)
2431
        builder.build()
2432
        self.db1.import_package(builder.dsc_name())
2433
        builder.native = False
2434
        builder.new_version(version3)
2435
        builder.build()
2436
        self.db1.import_package(builder.dsc_name())
2437
        rh1 = self.tree1.branch.revision_history()
2438
        up_rh1 = self.up_tree1.branch.revision_history()
2439
        self.assertEqual(len(rh1), 4)
2440
        self.assertEqual(len(up_rh1), 1)
2441
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
2442
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[2])
2443
        rev_tree3 = self.tree1.branch.repository.revision_tree(rh1[3])
2444
        self.assertEqual(rev_tree1.get_parent_ids(), [up_rh1[0]])
2445
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[1]])
2446
        self.assertEqual(rev_tree3.get_parent_ids(), [rh1[2]])
2447
        self.assertEqual(self.db1.revid_of_version(version1), rh1[1])
2448
        self.assertEqual(self.db1.revid_of_version(version2), rh1[2])
2449
        self.assertEqual(self.db1.revid_of_version(version3), rh1[3])
2450
        self.assertEqual(self.db1.revid_of_upstream_version(version1),
2451
                up_rh1[0])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2452
        self.tree1.lock_read()
2453
        self.addCleanup(self.tree1.unlock)
235.1.2 by James Westby
Handle more transitions between native and non-native.
2454
        self.assertFalse(self.db1.is_version_native(version1))
2455
        self.assertTrue(self.db1.is_version_native(version2))
2456
        self.assertFalse(self.db1.is_version_native(version3))
2457
2458
    def test_import_to_native_and_back_new_upstream(self):
2459
        """Non-native to native and back with a new upstream version.
2460
           
2461
        As the native version was on the same upstream as a non-native
2462
        version we assume that it was accidental, and so don't include
2463
        the native revision in the upstream branch's history.
2464
2465
        As we get a new upstream we want to link that to the previous
2466
        upstream.
2467
        """
2468
        version1 = Version("1.0-1")
2469
        version2 = Version("1.0-2")
2470
        version3 = Version("1.1-1")
2471
        builder = SourcePackageBuilder("package", version1)
2472
        builder.add_default_control()
2473
        builder.build()
2474
        self.db1.import_package(builder.dsc_name())
2475
        builder.native = True
2476
        builder.new_version(version2)
2477
        builder.build()
2478
        self.db1.import_package(builder.dsc_name())
2479
        builder.native = False
2480
        builder.new_version(version3)
2481
        builder.build()
2482
        self.db1.import_package(builder.dsc_name())
2483
        rh1 = self.tree1.branch.revision_history()
2484
        up_rh1 = self.up_tree1.branch.revision_history()
2485
        self.assertEqual(len(rh1), 4)
2486
        self.assertEqual(len(up_rh1), 2)
2487
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
2488
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[2])
2489
        rev_tree3 = self.tree1.branch.repository.revision_tree(rh1[3])
2490
        up_rev_tree1 = \
2491
                self.up_tree1.branch.repository.revision_tree(up_rh1[0])
2492
        up_rev_tree2 = \
2493
                self.up_tree1.branch.repository.revision_tree(up_rh1[1])
2494
        self.assertEqual(rev_tree1.get_parent_ids(), [up_rh1[0]])
2495
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[1]])
2496
        self.assertEqual(rev_tree3.get_parent_ids(), [rh1[2], up_rh1[1]])
2497
        self.assertEqual(up_rev_tree2.get_parent_ids(), [up_rh1[0]])
2498
        self.assertEqual(self.db1.revid_of_version(version1), rh1[1])
2499
        self.assertEqual(self.db1.revid_of_version(version2), rh1[2])
2500
        self.assertEqual(self.db1.revid_of_version(version3), rh1[3])
2501
        self.assertEqual(self.db1.revid_of_upstream_version(version1),
2502
                up_rh1[0])
2503
        self.assertEqual(self.db1.revid_of_upstream_version(version3),
2504
                up_rh1[1])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2505
        self.tree1.lock_read()
2506
        self.addCleanup(self.tree1.unlock)
235.1.2 by James Westby
Handle more transitions between native and non-native.
2507
        self.assertFalse(self.db1.is_version_native(version1))
2508
        self.assertTrue(self.db1.is_version_native(version2))
2509
        self.assertFalse(self.db1.is_version_native(version3))
2510
2511
    def test_import_to_native_and_back_all_different_upstreams(self):
2512
        """Non-native to native and back with all different upstreams.
2513
           
2514
        In this case we want to assume the package was "intended" to
2515
        be native, and so we include the native version in the upstream
2516
        history (i.e. the upstream part of the last version has
2517
        the second version's packaging branch revision as the second
2518
        parent).
2519
        """
2520
        version1 = Version("1.0-1")
2521
        version2 = Version("1.1")
2522
        version3 = Version("1.2-1")
2523
        builder = SourcePackageBuilder("package", version1)
2524
        builder.add_default_control()
2525
        builder.build()
2526
        self.db1.import_package(builder.dsc_name())
2527
        builder.native = True
2528
        builder.new_version(version2)
2529
        builder.build()
2530
        self.db1.import_package(builder.dsc_name())
2531
        builder.native = False
2532
        builder.new_version(version3)
2533
        builder.build()
2534
        self.db1.import_package(builder.dsc_name())
2535
        rh1 = self.tree1.branch.revision_history()
2536
        up_rh1 = self.up_tree1.branch.revision_history()
2537
        self.assertEqual(len(rh1), 4)
2538
        self.assertEqual(len(up_rh1), 2)
2539
        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
2540
        rev_tree2 = self.tree1.branch.repository.revision_tree(rh1[2])
2541
        rev_tree3 = self.tree1.branch.repository.revision_tree(rh1[3])
2542
        up_rev_tree1 = \
2543
                self.up_tree1.branch.repository.revision_tree(up_rh1[0])
2544
        up_rev_tree2 = \
2545
                self.up_tree1.branch.repository.revision_tree(up_rh1[1])
2546
        self.assertEqual(rev_tree1.get_parent_ids(), [up_rh1[0]])
2547
        self.assertEqual(rev_tree2.get_parent_ids(), [rh1[1]])
2548
        self.assertEqual(rev_tree3.get_parent_ids(), [rh1[2], up_rh1[1]])
2549
        self.assertEqual(up_rev_tree2.get_parent_ids(), [up_rh1[0], rh1[2]])
2550
        self.assertEqual(self.db1.revid_of_version(version1), rh1[1])
2551
        self.assertEqual(self.db1.revid_of_version(version2), rh1[2])
2552
        self.assertEqual(self.db1.revid_of_version(version3), rh1[3])
2553
        self.assertEqual(self.db1.revid_of_upstream_version(version1),
2554
                up_rh1[0])
2555
        self.assertEqual(self.db1.revid_of_upstream_version(version3),
2556
                up_rh1[1])
258 by James Westby
Also record the native status in the working tree when using DistributionBranch.
2557
        self.tree1.lock_read()
2558
        self.addCleanup(self.tree1.unlock)
235.1.2 by James Westby
Handle more transitions between native and non-native.
2559
        self.assertFalse(self.db1.is_version_native(version1))
2560
        self.assertTrue(self.db1.is_version_native(version2))
2561
        self.assertFalse(self.db1.is_version_native(version3))
2562
        # TODO: test that file-ids added in the native version
2563
        # are used in the second non-native upstream
2564
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2565
2566
class SourcePackageBuilder(object):
2567
234 by James Westby
Support basic importing of native packages.
2568
    def __init__(self, name, version, native=False):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2569
        self.upstream_files = {}
2570
        self.debian_files = {}
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2571
        self.name = name
234 by James Westby
Support basic importing of native packages.
2572
        self.native = native
235.1.1 by James Westby
Intial support for transitioning from native to non-native and back.
2573
        self._cl = Changelog()
2574
        self.new_version(version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2575
2576
    def add_upstream_file(self, name, content=None):
2577
        self.add_upstream_files([(name, content)])
2578
2579
    def add_upstream_files(self, files):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2580
        for new_file in files:
2581
            self.upstream_files[new_file[0]] = new_file[1]
2582
2583
    def remove_upstream_file(self, filename):
2584
        del self.upstream_files[filename]
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2585
2586
    def add_debian_file(self, name, content=None):
2587
        self.add_debian_files([(name, content)])
2588
2589
    def add_debian_files(self, files):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2590
        for new_file in files:
2591
            self.debian_files[new_file[0]] = new_file[1]
2592
2593
    def remove_debian_file(self, filename):
2594
        del self.debian_files[filename]
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2595
231 by James Westby
Use dpkg-source to build the source packages for testing.
2596
    def add_default_control(self):
2597
        text = """Source: %s\n""" % self.name
2598
        self.add_debian_file("debian/control", text)
2599
233 by James Westby
Make the SourcePackageBuilder easier to use.
2600
    def new_version(self, version):
2601
        self._cl.new_block(package=self.name, version=version,
231 by James Westby
Use dpkg-source to build the source packages for testing.
2602
                distributions="unstable", urgency="low",
2603
                author="Maint <maint@maint.org>",
2604
                date="Wed, 19 Mar 2008 21:27:37 +0000")
233 by James Westby
Make the SourcePackageBuilder easier to use.
2605
        self._cl.add_change("  * foo")
231 by James Westby
Use dpkg-source to build the source packages for testing.
2606
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2607
    def dsc_name(self):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2608
        return "%s_%s.dsc" % (self.name, str(self._cl.version))
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2609
2610
    def _make_files(self, files_list, basedir):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2611
        for (path, content) in files_list.items():
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2612
            dirname = os.path.dirname(path)
2613
            if dirname is not None and dirname != "":
231 by James Westby
Use dpkg-source to build the source packages for testing.
2614
                if not os.path.exists(os.path.join(basedir, dirname)):
2615
                    os.makedirs(os.path.join(basedir, dirname))
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2616
            f = open(os.path.join(basedir, path), 'wb')
2617
            try:
2618
                if content is None:
2619
                    content = ''
2620
                f.write(content)
2621
            finally:
2622
                f.close()
2623
2624
    def basedir(self):
233 by James Westby
Make the SourcePackageBuilder easier to use.
2625
        return self.name + "-" + str(self._cl.version.upstream_version)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2626
229 by James Westby
Use file ids from other trees.
2627
    def _make_base(self):
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2628
        basedir = self.basedir()
2629
        os.mkdir(basedir)
2630
        self._make_files(self.upstream_files, basedir)
229 by James Westby
Use file ids from other trees.
2631
        return basedir
2632
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2633
    def build(self):
229 by James Westby
Use file ids from other trees.
2634
        basedir = self._make_base()
234 by James Westby
Support basic importing of native packages.
2635
        if not self.native:
2636
            orig_basedir = basedir + ".orig"
2637
            shutil.copytree(basedir, orig_basedir)
2638
            cmd = "dpkg-source -sa -b %s" % (basedir)
237 by James Westby
Don't override the tip of a branch when importing.
2639
            if os.path.exists("%s_%s.orig.tar.gz"
2640
                    % (self.name, self._cl.version.upstream_version)):
2641
                cmd = "dpkg-source -ss -b %s" % (basedir)
234 by James Westby
Support basic importing of native packages.
2642
        else:
2643
            cmd = "dpkg-source -sn -b %s" % (basedir)
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2644
        self._make_files(self.debian_files, basedir)
233 by James Westby
Make the SourcePackageBuilder easier to use.
2645
        self._make_files({"debian/changelog": str(self._cl)}, basedir)
234 by James Westby
Support basic importing of native packages.
2646
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
2647
                stderr=subprocess.PIPE)
231 by James Westby
Use dpkg-source to build the source packages for testing.
2648
        ret = proc.wait()
2649
        assert ret == 0, "dpkg-source failed, output:\n%s\n%s" % \
2650
                (proc.stdout.read(), proc.stderr.read())
228 by James Westby
Add DistributionBranch that allows you to import multiple branches in parallel.
2651
        shutil.rmtree(basedir)
2652