1
# Copyright (C) 2005 Canonical Limited
2
# Authors: Robert Collins <robert.collins@canonical.com>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from bzrlib.selftest import TestCaseInTempDir, TestCase
19
from bzrlib.selftest.blackbox import has_symlinks
25
from bzrlib.plugins.bzrtools.baz_import import (import_version, revision_id,
27
from bzrlib.errors import NoSuchRevision
29
from StringIO import StringIO
31
from testresources import (TestResource, TestLoader, OptimisingTestSuite,
33
from bzrlib.plugins.bzrtools.fai import namespace_previous
34
from bzrlib.branch import Branch
38
return OptimisingTestSuite()
39
return TestLoader().loadTestsFromName(__name__)
42
class BazTreeResource(TestResource):
45
os.environ['HOME'] = self._oldhome
46
shutil.rmtree(self._tmpdir)
49
self._tmpdir = tempfile.mkdtemp()
50
self._homedir = os.path.join(self._tmpdir, 'home')
51
self._oldhome = os.environ['HOME']
52
os.mkdir(self._homedir)
53
os.environ['HOME'] = self._homedir
55
self._archiveroot = os.path.join(self._tmpdir, 'archive')
56
self._archive = pybaz.make_archive('demo@DONOTUSE', str(self._archiveroot))
57
pybaz.set_my_id("Test User<test@example.org>")
59
self.make_empty_import()
61
self._empty_tag = 'demo@DONOTUSE/c--empty-tag--0'
62
self._empty_tag_bzr = revision_id(self._empty_tag + '--base-0')
63
pybaz.Revision('demo@DONOTUSE/c--import--0--base-0').make_continuation(
64
pybaz.Version(self._empty_tag))
66
self._empty_merged_tag = 'demo@DONOTUSE/c--empty-merged-tag--0'
67
self._empty_merged_tag_bzr_base = revision_id(self._empty_merged_tag
69
self._empty_merged_tag_bzr = revision_id(self._empty_merged_tag
71
pybaz.Revision('demo@DONOTUSE/c--import--0--base-0').make_continuation(
72
pybaz.Version(self._empty_merged_tag))
73
tree = pybaz.Revision(self._empty_merged_tag + '--base-0').get(
74
os.path.join(self._tmpdir, 'tree'))
75
tree.star_merge(self._empty_tag,
76
pybaz.Version('demo@DONOTUSE/c--import--0'))
77
msg = tree.log_message()
78
msg["summary"]="did a merge, yarh"
80
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
82
# tree, two commits, includes merge of other branch
83
self._empty_merged_tag_2 = 'demo@DONOTUSE/c--empty-tag-2--0'
84
self._empty_merged_tag_2_bzr_base = revision_id(self._empty_merged_tag_2 + '--base-0')
85
self._empty_merged_tag_2_bzr = revision_id(self._empty_merged_tag_2 + '--patch-1')
86
pybaz.Revision('demo@DONOTUSE/c--import--0--base-0').make_continuation(
87
pybaz.Version(self._empty_merged_tag_2))
88
tree = pybaz.Revision(self._empty_merged_tag_2 + '--base-0').get (
89
os.path.join(self._tmpdir, 'tree'))
90
tree.star_merge(self._empty_merged_tag,
91
pybaz.Version('demo@DONOTUSE/c--import--0'))
92
msg = tree.log_message()
93
msg["summary"] = "merge in a merged tree."
95
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
97
self.make_import_symlink()
98
self.make_missing_ancestor()
100
def make_import_symlink(self):
101
self._import_symlink = 'demo@DONOTUSE/c--import-symlink--0'
102
self._import_symlink_bzr = revision_id(self._import_symlink + '--base-0')
103
os.mkdir(os.path.join(self._tmpdir, 'tree'))
104
tree = pybaz.init_tree(os.path.join(self._tmpdir, 'tree'),
105
self._import_symlink)
106
os.symlink('missing-file-name',
107
os.path.join(self._tmpdir, 'tree', 'alink'))
108
tree.add_tag('alink')
109
id_file = open(os.path.join(tree, '.arch-ids', 'alink.id'), 'w')
110
id_file.write('symlink_tag\n')
112
msg = tree.log_message()
113
msg["summary"] = "Import with a symlink"
115
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
117
def make_empty_import(self):
118
self._import = 'demo@DONOTUSE/c--import--0'
119
os.mkdir(os.path.join(self._tmpdir, 'tree'))
120
tree = pybaz.init_tree(os.path.join(self._tmpdir, 'tree'), self._import)
121
msg = tree.log_message()
122
msg["summary"] = "I am importing now"
124
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
126
def make_missing_ancestor(self):
127
self._archivegoneroot = os.path.join(self._tmpdir, 'archivegone')
128
self._archive = pybaz.make_archive('demo-gone@DONOTUSE',
129
str(self._archivegoneroot))
130
self._missing_import = 'demo-gone@DONOTUSE/c--import--0'
131
self._missing_import_bzr = revision_id(self._missing_import
133
self._missing_ancestor = 'demo@DONOTUSE/c--gone--0'
134
self._missing_ancestor_bzr = revision_id(self._missing_ancestor
136
os.mkdir(os.path.join(self._tmpdir, 'tree'))
137
tree = pybaz.init_tree(os.path.join(self._tmpdir, 'tree'),
138
self._missing_import)
139
msg = tree.log_message()
140
msg["summary"] = "I am importing now"
142
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
143
# tag into the kept archive
144
pybaz.Revision(self._missing_import + '--base-0').make_continuation(
145
pybaz.Version(self._missing_ancestor))
146
# and make it inaccessible
147
pybaz.Archive('demo-gone@DONOTUSE').unregister()
150
def _makeResource(self):
151
return BazTreeResource()
154
def _cleanResource(self, resource):
158
class TestImportBranch(TestCaseInTempDir):
160
_resources = [("_baz", BazTreeResource)]
163
TestCaseInTempDir.setUp(self)
164
ResourcedTestCase.setUpResources(self)
165
os.environ['HOME'] = self._baz._homedir
166
self.output = StringIO()
169
ResourcedTestCase.tearDownResources(self)
170
TestCaseInTempDir.tearDown(self)
172
def collect(self, text):
173
self.output.write(text)
174
self.output.write("\n")
176
def test_import_empty(self):
177
import_version('output', pybaz.Version(self._baz._import), self.collect)
179
# one commit, no files, revision identifier of 'demo@DONOTUSE_c--import--0--base-0'
180
branch = Branch.open('output')
181
self.assertEqual(branch.revision_history(),
182
['Arch-1:demo@DONOTUSE%c--import--0--base-0'])
183
rev = branch.get_revision('Arch-1:demo@DONOTUSE%c--import--0--base-0')
185
import_version('output2', pybaz.Version('demo@DONOTUSE/c--import--0'),
187
branch2 = Branch.open('output2')
188
self.assertEqual(branch.revision_history(), branch2.revision_history())
189
rev2 = branch2.get_revision('Arch-1:demo@DONOTUSE%c--import--0--base-0')
190
# they must be the same
191
self.assertEqual(rev, rev2)
193
# and we should get some expected values:
194
self.assertEqual(rev.committer, "Test User<test@example.org>")
195
self.assertEqual(rev.message, "I am importing now")
196
self.assertEqual(rev.revision_id,
197
"Arch-1:demo@DONOTUSE%c--import--0--base-0")
199
def test_empty_tagged(self):
200
import_version('output', pybaz.Version(self._baz._empty_tag),
203
# two commits, no files, revision identifiers of
204
# 'demo@DONOTUSE_c--import--0--base-0' and
205
# self._baz._empty_tag_bzr
206
branch = Branch.open('output')
207
self.assertEqual(branch.revision_history(),
208
['Arch-1:demo@DONOTUSE%c--import--0--base-0',
209
self._baz._empty_tag_bzr])
210
rev = branch.get_revision(self._baz._empty_tag_bzr)
212
import_version('output2', pybaz.Version(self._baz._empty_tag),
214
branch2 = Branch.open('output2')
215
self.assertEqual(branch.revision_history(), branch2.revision_history())
216
rev2 = branch2.get_revision(self._baz._empty_tag_bzr)
217
# they must be the same
218
self.assertEqual(rev, rev2)
220
# and we should get some expected values:
221
self.assertEqual(rev.committer, "Test User<test@example.org>")
222
self.assertEqual(rev.message, "tag of demo@DONOTUSE/c--import--0--base-0")
223
self.assertEqual(rev.revision_id, self._baz._empty_tag_bzr)
225
def test_empty_merged_tagged(self):
226
import_version('output', pybaz.Version(self._baz._empty_merged_tag),
229
# two commits, no files, revision identifiers of
230
# 'demo@DONOTUSE_c--import--0--base-0' and
231
# self._baz._empty_merged_tag_bzr_base
232
# self._baz._empty_merged_tag_bzr
233
# and a merged revision from the latter of
234
# self._baz._empty_tag_bzr
235
branch = Branch.open('output')
236
self.assertEqual(branch.revision_history(),
237
['Arch-1:demo@DONOTUSE%c--import--0--base-0',
238
self._baz._empty_merged_tag_bzr_base,
239
self._baz._empty_merged_tag_bzr])
241
import_version('output2', pybaz.Version(self._baz._empty_merged_tag),
243
branch2 = Branch.open('output2')
244
# and import what we should be merged up against for checking with.
245
import_version('output3', pybaz.Version(self._baz._empty_tag),
247
branch3 = Branch.open('output3')
249
self.assertEqual(branch.revision_history(), branch2.revision_history())
250
self.assertNotEqual(branch.revision_history(), branch3.revision_history())
251
# check revisions in the history.
252
rev = branch.get_revision(self._baz._empty_merged_tag_bzr_base)
253
rev2 = branch2.get_revision(self._baz._empty_merged_tag_bzr_base)
254
# they must be the same
255
self.assertEqual(rev, rev2)
256
# and we should get some expected values:
257
self.assertEqual(rev.committer, "Test User<test@example.org>")
258
self.assertEqual(rev.message, "tag of demo@DONOTUSE/c--import--0--base-0")
259
self.assertEqual(rev.revision_id, self._baz._empty_merged_tag_bzr_base)
261
# check next revisions in the history.
262
rev = branch.get_revision(self._baz._empty_merged_tag_bzr)
263
rev2 = branch2.get_revision(self._baz._empty_merged_tag_bzr)
264
# they must be the same
265
self.assertEqual(rev, rev2)
266
# and we should get some expected values:
267
self.assertEqual(rev.committer, "Test User<test@example.org>")
268
self.assertEqual(rev.message, "did a merge, yarh")
269
self.assertEqual(rev.revision_id, self._baz._empty_merged_tag_bzr)
270
self.assertEqual(rev.parent_ids[0],
271
self._baz._empty_merged_tag_bzr_base)
272
self.assertEqual(rev.parent_ids[1], self._baz._empty_tag_bzr)
274
# this tree should have nothing missing from that tree.
275
# FIXME there is no code for this right now.
276
# self.assertEqual(branch.missing_revisions(branch3), [])
278
def test_merge_branch_with_merges(self):
279
import_version('output', pybaz.Version(self._baz._empty_merged_tag_2),
282
# two commits, no files, revision identifiers of
283
# 'demo@DONOTUSE_c--import--0--base-0' and
284
# self._baz._empty_merged_tag_2_bzr_base
285
# self._baz._empty_merged_tag_2_bzr
286
# and a merged revision from the latter of
287
# self._baz._empty_merged_tag_bzr
288
branch = Branch.open('output')
289
self.assertEqual(branch.revision_history(),
290
['Arch-1:demo@DONOTUSE%c--import--0--base-0',
291
self._baz._empty_merged_tag_2_bzr_base,
292
self._baz._empty_merged_tag_2_bzr])
294
import_version('output2', pybaz.Version(self._baz._empty_merged_tag_2),
296
branch2 = Branch.open('output2')
297
# and import what we should be merged up against for checking with.
298
import_version('output3', pybaz.Version(self._baz._empty_merged_tag),
300
branch3 = Branch.open('output3')
302
self.assertEqual(branch.revision_history(), branch2.revision_history())
303
self.assertNotEqual(branch.revision_history(), branch3.revision_history())
304
# check revisions in the history.
305
rev = branch.get_revision(self._baz._empty_merged_tag_2_bzr_base)
306
rev2 = branch2.get_revision(self._baz._empty_merged_tag_2_bzr_base)
307
# they must be the same
308
self.assertEqual(rev, rev2)
309
# and we should get some expected values:
310
self.assertEqual(rev.committer, "Test User<test@example.org>")
311
self.assertEqual(rev.message, "tag of demo@DONOTUSE/c--import--0--base-0")
312
self.assertEqual(rev.revision_id, self._baz._empty_merged_tag_2_bzr_base)
314
# check next revisions in the history.
315
rev = branch.get_revision(self._baz._empty_merged_tag_2_bzr)
316
rev2 = branch2.get_revision(self._baz._empty_merged_tag_2_bzr)
317
# they must be the same
318
self.assertEqual(rev, rev2)
319
# and we should get some expected values:
320
self.assertEqual(rev.committer, "Test User<test@example.org>")
321
self.assertEqual(rev.message, "merge in a merged tree.")
322
self.assertEqual(rev.revision_id, self._baz._empty_merged_tag_2_bzr)
323
self.assertEqual(rev.parent_ids[0],
324
self._baz._empty_merged_tag_2_bzr_base)
325
self.assertEqual(rev.parent_ids[1],
326
self._baz._empty_merged_tag_bzr)
328
# this tree should have nothing missing from that tree.
329
# FIXME there is no code for this right now.
330
# self.assertEqual(branch.missing_revisions(branch3), [])
332
def test_import_symlink(self):
333
import_version('output', pybaz.Version(self._baz._import_symlink),
336
# one commit, no files, revision identifier of 'demo@DONOTUSE_c--import--0--base-0'
337
branch = Branch.open('output')
338
self.assertEqual(branch.revision_history(),
339
[self._baz._import_symlink_bzr])
340
rev = branch.get_revision(self._baz._import_symlink_bzr)
342
import_version('output2', pybaz.Version(self._baz._import_symlink),
344
branch2 = Branch.open('output2')
345
self.assertEqual(branch.revision_history(), branch2.revision_history())
346
rev2 = branch2.get_revision(self._baz._import_symlink_bzr)
347
# they must be the same
348
self.assertEqual(rev, rev2)
350
# and we should get some expected values:
351
self.assertEqual(rev.committer, "Test User<test@example.org>")
352
self.assertEqual(rev.message, "Import with a symlink")
353
self.assertEqual(rev.revision_id, self._baz._import_symlink_bzr)
355
# and we want the symlink alink with target 'missing-file-name'
356
inv = branch.get_inventory(rev.revision_id)
357
self.assertEqual(inv.path2id('alink'), 'x_symlink_tag')
358
entry = inv['x_symlink_tag']
359
self.assertEqual(entry.kind, 'symlink')
360
self.assertEqual(entry.symlink_target, 'missing-file-name')
362
def test_missing_ancestor(self):
363
import_version('output', pybaz.Version(self._baz._missing_ancestor),
366
# one commits, no files, revision identifiers of
367
# 'demo@DONOTUSE_c--gone--0--base-0' and
368
# a merge of demo-gone@DONOTUSE%c--import--0
369
branch = Branch.open('output')
370
self.assertEqual(branch.revision_history(),
371
[self._baz._missing_ancestor_bzr])
372
rev = branch.get_revision(self._baz._missing_ancestor_bzr)
374
import_version('output2', pybaz.Version(self._baz._missing_ancestor),
376
branch2 = Branch.open('output2')
377
self.assertEqual(branch.revision_history(), branch2.revision_history())
378
rev2 = branch2.get_revision(self._baz._missing_ancestor_bzr)
379
# they must be the same
380
self.assertEqual(rev, rev2)
382
# and we should get some expected values:
383
self.assertEqual(rev.committer, "Test User<test@example.org>")
384
self.assertEqual(rev.message, "tag of demo-gone@DONOTUSE/c--import--0--base-0")
385
self.assertEqual(rev.revision_id, self._baz._missing_ancestor_bzr)
386
self.assertEqual(rev.parent_ids[0], self._baz._missing_import_bzr)
387
self.assertEqual(1, len(rev.parent_ids))
389
# must NOT be able to get the merged evision
390
self.assertRaises(NoSuchRevision, branch.get_revision,
391
self._baz._missing_import_bzr)
394
class TestNamespacePrevious(TestCase):
398
self.version = pybaz.Version('foo@example.com/c--b--0')
400
def test_base0_none(self):
401
self.assertEqual(namespace_previous(self.version['base-0']), None)
403
def test_patch1_base0(self):
404
self.assertEqual(namespace_previous(self.version['patch-1']),
405
self.version['base-0'])
407
def test_patch3000_patch2999(self):
408
self.assertEqual(namespace_previous(self.version['patch-3000']),
409
self.version['patch-2999'])
411
def test_version0_raises(self):
412
self.assertRaises(RuntimeError, namespace_previous,
413
self.version['version-0'])
415
def test_version1_version0(self):
416
self.assertEqual(namespace_previous(self.version['versionfix-1']),
417
self.version['version-0'])
419
def test_version3000_patch2999(self):
420
self.assertEqual(namespace_previous(self.version['versionfix-3000']),
421
self.version['versionfix-2999'])
423
class TestNamespaceMapping(TestCase):
425
def test_namespace_mapping_branch(self):
426
from baz_import import map_namespace
427
branch = pybaz.Branch('foo@example.com/c--b')
428
self.assertRaises(pybaz.errors.NamespaceError, map_namespace, branch)
429
self.assertEqual('c/b', map_namespace(branch['0']))
430
self.assertEqual('c/0.1/b', map_namespace(branch['0.1']))
432
def test_namespace_mapping_no_branch(self):
433
from baz_import import map_namespace
434
category = pybaz.Category('foo@example.com/c')
435
self.assertRaises(pybaz.errors.NamespaceError, map_namespace, category)
436
self.assertEqual('c/+trunk',
437
map_namespace(pybaz.Version("%s--0" % category)))
438
self.assertEqual('c/0.1/+trunk',
439
map_namespace(pybaz.Version('%s--0.1' % category)))
442
class TestImport(TestCaseInTempDir):
445
TestCaseInTempDir.setUp(self)
446
self._oldhome = os.environ['HOME']
447
self._tmpdir = tempfile.mkdtemp()
448
self._homedir = os.path.join(self._tmpdir, 'home')
449
os.mkdir(self._homedir)
450
os.environ['HOME'] = self._homedir
451
self._archiveroot = os.path.join(self._tmpdir, 'archive')
452
self._archive = pybaz.make_archive('demo@DONOTUSE',
453
str(self._archiveroot))
456
os.environ['HOME'] = self._oldhome
457
shutil.rmtree(self._tmpdir)
458
TestCaseInTempDir.tearDown(self)
460
def make_import(self, namespace):
461
self._import = 'demo@DONOTUSE/%s' % namespace
462
os.mkdir(os.path.join(self._tmpdir, 'tree'))
463
tree = pybaz.init_tree(os.path.join(self._tmpdir, 'tree'), self._import)
464
msg = tree.log_message()
465
msg["summary"] = "I am importing now"
467
shutil.rmtree(os.path.join(self._tmpdir, 'tree'))
469
def test_cmd_exists(self):
470
from bzrlib.plugins.baz_import.baz_import import cmd_baz_import
472
def test_empty_archive(self):
473
command = cmd_baz_import()
474
command.run(os.path.join(self._tmpdir, 'output'), 'demo@DONOTUSE')
475
self.failUnless(os.path.exists(os.path.join(self._tmpdir,'output')))
477
len(list(os.walk(os.path.join(self._tmpdir,'output')))))
479
def test_two_branches(self):
480
self.make_import('c--0')
481
self.make_import('c1--branch--0.2')
482
command = cmd_baz_import()
483
command.run(os.path.join(self._tmpdir, 'output'), 'demo@DONOTUSE')
484
self.failUnless(os.path.exists(os.path.join(self._tmpdir,'output')))
485
self.failUnless(os.path.exists(os.path.join(self._tmpdir,'output', 'c','+trunk')))
486
self.failUnless(os.path.exists(os.path.join(self._tmpdir,'output', 'c1', '0.2','branch')))
488
len(list(os.walk(os.path.join(self._tmpdir,'output')))))
490
def test_run_twice(self):
491
self.make_import('c--0')
492
command = cmd_baz_import()
493
command.run(os.path.join(self._tmpdir, 'output'), 'demo@DONOTUSE')
494
command.run(os.path.join(self._tmpdir, 'output'), 'demo@DONOTUSE')