1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2006-2007 Jelmer Vernooij <jelmer@samba.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 """Commit and push tests."""
21 from bzrlib.branch import Branch, PullResult
22 from bzrlib.bzrdir import BzrDir
23 from bzrlib.errors import DivergedBranches, BzrError
24 from bzrlib.trace import mutter
25 from bzrlib.workingtree import WorkingTree
27 from commit import set_svn_revprops
29 from errors import RevpropChangeFailed
30 from mapping import MAPPING_VERSION
32 from remote import SvnRaTransport
33 from tests import TestCaseWithSubversionRepository
35 from svn.core import svn_time_to_cstring
37 class TestNativeCommit(TestCaseWithSubversionRepository):
38 def test_simple_commit(self):
39 self.make_client('d', 'dc')
40 self.build_tree({'dc/foo/bla': "data"})
41 self.client_add("dc/foo")
42 wt = self.open_checkout("dc")
43 revid = wt.commit(message="data")
44 self.assertEqual(wt.branch.generate_revision_id(1), revid)
45 self.client_update("dc")
46 self.assertEqual(wt.branch.generate_revision_id(1),
47 wt.branch.last_revision())
48 wt = WorkingTree.open("dc")
49 new_inventory = wt.branch.repository.get_inventory(
50 wt.branch.last_revision())
51 self.assertTrue(new_inventory.has_filename("foo"))
52 self.assertTrue(new_inventory.has_filename("foo/bla"))
54 def test_commit_message(self):
55 self.make_client('d', 'dc')
56 self.build_tree({'dc/foo/bla': "data"})
57 self.client_add("dc/foo")
58 wt = self.open_checkout("dc")
59 revid = wt.commit(message="data")
60 self.assertEqual(wt.branch.generate_revision_id(1), revid)
62 wt.branch.generate_revision_id(1), wt.branch.last_revision())
63 new_revision = wt.branch.repository.get_revision(
64 wt.branch.last_revision())
65 self.assertEqual(wt.branch.last_revision(), new_revision.revision_id)
66 self.assertEqual("data", new_revision.message)
68 def test_commit_rev_id(self):
69 self.make_client('d', 'dc')
70 self.build_tree({'dc/foo/bla': "data"})
71 self.client_add("dc/foo")
72 wt = self.open_checkout("dc")
73 revid = wt.commit(message="data", rev_id="some-revid-bla")
74 self.assertEqual("some-revid-bla", revid)
75 self.assertEqual(wt.branch.generate_revision_id(1), revid)
77 wt.branch.generate_revision_id(1), wt.branch.last_revision())
78 new_revision = wt.branch.repository.get_revision(
79 wt.branch.last_revision())
80 self.assertEqual(wt.branch.last_revision(), new_revision.revision_id)
82 def test_commit_local(self):
83 self.make_client('d', 'dc')
84 self.build_tree({'dc/foo/bla': "data"})
85 self.client_add("dc/foo")
86 wt = self.open_checkout("dc")
87 self.assertRaises(BzrError, wt.commit,
88 message="data", local=True)
90 def test_commit_committer(self):
91 self.make_client('d', 'dc')
92 self.build_tree({'dc/foo/bla': "data"})
93 self.client_add("dc/foo")
94 wt = self.open_checkout("dc")
95 revid = wt.commit(message="data", committer="john doe")
96 rev = wt.branch.repository.get_revision(revid)
97 self.assertEquals("john doe", rev.committer)
99 def test_commit_message_nordic(self):
100 self.make_client('d', 'dc')
101 self.build_tree({'dc/foo/bla': "data"})
102 self.client_add("dc/foo")
103 wt = self.open_checkout("dc")
104 revid = wt.commit(message=u"føø")
105 self.assertEqual(revid, wt.branch.generate_revision_id(1))
107 wt.branch.generate_revision_id(1), wt.branch.last_revision())
108 new_revision = wt.branch.repository.get_revision(
109 wt.branch.last_revision())
110 self.assertEqual(wt.branch.last_revision(), new_revision.revision_id)
111 self.assertEqual(u"føø", new_revision.message)
113 def test_commit_update(self):
114 self.make_client('d', 'dc')
115 self.build_tree({'dc/foo/bla': "data"})
116 self.client_add("dc/foo")
117 wt = self.open_checkout("dc")
118 wt.set_pending_merges(["some-ghost-revision"])
119 wt.commit(message="data")
121 wt.branch.generate_revision_id(1),
122 wt.branch.last_revision())
124 def test_commit_parents(self):
125 repos_url = self.make_client('d', 'dc')
126 self.build_tree({'dc/foo/bla': "data"})
127 self.client_add("dc/foo")
128 wt = self.open_checkout("dc")
129 wt.set_pending_merges(["some-ghost-revision"])
130 self.assertEqual(["some-ghost-revision"], wt.pending_merges())
131 wt.commit(message="data")
132 self.assertEqual("some-ghost-revision\n",
133 self.client_get_prop(repos_url, "bzr:ancestry:v3-none", 1))
134 self.assertEqual([wt.branch.generate_revision_id(0), "some-ghost-revision"],
135 wt.branch.repository.revision_parents(
136 wt.branch.last_revision()))
138 def test_commit_rename_file(self):
139 repos_url = self.make_client('d', 'dc')
140 self.build_tree({'dc/foo': "data"})
141 self.client_add("dc/foo")
142 wt = self.open_checkout("dc")
143 wt.set_pending_merges(["some-ghost-revision"])
144 oldid = wt.path2id("foo")
145 wt.commit(message="data")
146 wt.rename_one("foo", "bar")
147 wt.commit(message="doe")
148 paths = self.client_log("dc", 2, 0)[2][0]
149 self.assertEquals('D', paths["/foo"].action)
150 self.assertEquals('A', paths["/bar"].action)
151 self.assertEquals('/foo', paths["/bar"].copyfrom_path)
152 self.assertEquals(1, paths["/bar"].copyfrom_rev)
153 self.assertEquals("bar\t%s\n" % oldid,
154 self.client_get_prop(repos_url, "bzr:file-ids", 2))
156 def test_commit_rename_file_from_directory(self):
157 repos_url = self.make_client('d', 'dc')
158 self.build_tree({'dc/adir/foo': "data"})
159 self.client_add("dc/adir")
160 wt = self.open_checkout("dc")
161 wt.commit(message="data")
162 wt.rename_one("adir/foo", "bar")
163 self.assertFalse(wt.has_filename("adir/foo"))
164 self.assertTrue(wt.has_filename("bar"))
165 wt.commit(message="doe")
166 paths = self.client_log("dc", 2, 0)[2][0]
167 self.assertEquals('D', paths["/adir/foo"].action)
168 self.assertEquals('A', paths["/bar"].action)
169 self.assertEquals('/adir/foo', paths["/bar"].copyfrom_path)
170 self.assertEquals(1, paths["/bar"].copyfrom_rev)
172 def test_commit_revision_id(self):
173 repos_url = self.make_client('d', 'dc')
174 wt = self.open_checkout("dc")
175 self.build_tree({'dc/foo/bla': "data", 'dc/bla': "otherdata"})
177 wt.commit(message="data")
179 branch = Branch.open(repos_url)
180 builder = branch.get_commit_builder([branch.last_revision()],
181 revision_id="my-revision-id")
182 tree = branch.repository.revision_tree(branch.last_revision())
183 new_tree = copy(tree)
184 ie = new_tree.inventory.root
186 builder.record_entry_contents(ie, [tree.inventory], '', new_tree,
188 builder.finish_inventory()
189 builder.commit("foo")
191 self.assertEqual("3 my-revision-id\n",
192 self.client_get_prop("dc",
193 "bzr:revision-id:v%d-none" % MAPPING_VERSION, 2))
195 def test_commit_metadata(self):
196 repos_url = self.make_client('d', 'dc')
197 wt = self.open_checkout("dc")
198 self.build_tree({'dc/foo/bla': "data", 'dc/bla': "otherdata"})
200 wt.commit(message="data")
202 branch = Branch.open(repos_url)
203 builder = branch.get_commit_builder([branch.last_revision()],
204 timestamp=4534.0, timezone=2, committer="fry",
205 revision_id="my-revision-id")
206 tree = branch.repository.revision_tree(branch.last_revision())
207 new_tree = copy(tree)
208 ie = new_tree.inventory.root
210 builder.record_entry_contents(ie, [tree.inventory], '', new_tree, None)
211 builder.finish_inventory()
212 builder.commit("foo")
214 self.assertEqual("3 my-revision-id\n",
215 self.client_get_prop("dc", "bzr:revision-id:v%d-none" % MAPPING_VERSION, 2))
218 "timestamp: 1970-01-01 01:15:36.000000000 +0000\ncommitter: fry\n",
219 self.client_get_prop("dc", "bzr:revision-info", 2))
222 repo = self.make_client('d', 'sc')
225 self.client_copy(a, b)
226 self.client_delete(a)
227 self.client_commit('sc', '.')
228 self.client_update('sc')
229 self.build_tree({'sc/de/foo':'data', 'sc/de/bar':'DATA'})
230 self.client_add('sc/de')
231 self.client_commit('sc', 'blah') #1
232 self.client_update('sc')
233 os.mkdir('sc/de/trunk')
234 self.client_add('sc/de/trunk')
235 mv(('sc/de/foo', 'sc/de/trunk'), ('sc/de/bar', 'sc/de/trunk')) #2
236 mv(('sc/de', 'sc/pyd')) #3
237 self.client_delete('sc/pyd/trunk/foo')
238 self.client_commit('sc', '.') #4
239 self.client_update('sc')
241 self.make_checkout(repo + '/pyd/trunk', 'pyd')
242 self.assertEqual("DATA", open('pyd/bar').read())
244 olddir = BzrDir.open("pyd")
246 newdir = olddir.sprout("bc")
247 newdir.open_branch().pull(olddir.open_branch())
248 wt = newdir.open_workingtree()
249 self.assertEqual("DATA", open('bc/bar').read())
250 open('bc/bar', 'w').write('data')
251 wt.commit(message="Commit from Bzr")
252 olddir.open_branch().pull(newdir.open_branch())
254 self.client_update('pyd')
255 self.assertEqual("data", open('pyd/bar').read())
258 class TestPush(TestCaseWithSubversionRepository):
260 super(TestPush, self).setUp()
261 self.repos_url = self.make_client('d', 'sc')
263 self.build_tree({'sc/foo/bla': "data"})
264 self.client_add("sc/foo")
265 self.client_commit("sc", "foo")
267 self.olddir = self.open_checkout_bzrdir("sc")
269 self.newdir = self.olddir.sprout("dc")
271 def test_empty(self):
272 self.assertEqual(0, int(self.olddir.open_branch().pull(
273 self.newdir.open_branch())))
275 def test_empty_result(self):
276 result = self.olddir.open_branch().pull(self.newdir.open_branch())
277 self.assertIsInstance(result, PullResult)
278 self.assertEqual(result.old_revno, self.olddir.open_branch().revno())
279 self.assertEqual(result.master_branch, None)
280 self.assertEqual(result.source_branch.bzrdir.root_transport.base,
281 self.newdir.root_transport.base)
283 def test_child(self):
284 self.build_tree({'sc/foo/bar': "data"})
285 self.client_add("sc/foo/bar")
286 self.client_commit("sc", "second message")
288 self.assertEqual(0, int(self.olddir.open_branch().pull(
289 self.newdir.open_branch())))
291 def test_diverged(self):
292 self.build_tree({'sc/foo/bar': "data"})
293 self.client_add("sc/foo/bar")
294 self.client_commit("sc", "second message")
296 olddir = BzrDir.open("sc")
298 self.build_tree({'dc/file': 'data'})
299 wt = self.newdir.open_workingtree()
301 wt.commit(message="Commit from Bzr")
303 self.assertRaises(DivergedBranches,
304 olddir.open_branch().pull,
305 self.newdir.open_branch())
307 def test_change(self):
308 self.build_tree({'dc/foo/bla': 'other data'})
309 wt = self.newdir.open_workingtree()
310 wt.commit(message="Commit from Bzr")
312 self.olddir.open_branch().pull(self.newdir.open_branch())
314 repos = self.olddir.find_repository()
315 inv = repos.get_inventory(repos.generate_revision_id(2, "", "none"))
316 self.assertEqual(repos.generate_revision_id(2, "", "none"),
317 inv[inv.path2id('foo/bla')].revision)
318 self.assertEqual(wt.branch.last_revision(),
319 repos.generate_revision_id(2, "", "none"))
320 self.assertEqual(wt.branch.last_revision(),
321 self.olddir.open_branch().last_revision())
322 self.assertEqual("other data",
323 repos.revision_tree(repos.generate_revision_id(2, "", "none")).get_file_text( inv.path2id("foo/bla")))
325 def test_simple(self):
326 self.build_tree({'dc/file': 'data'})
327 wt = self.newdir.open_workingtree()
329 wt.commit(message="Commit from Bzr")
331 self.olddir.open_branch().pull(self.newdir.open_branch())
333 repos = self.olddir.find_repository()
334 inv = repos.get_inventory(repos.generate_revision_id(2, "", "none"))
335 self.assertTrue(inv.has_filename('file'))
336 self.assertEqual(wt.branch.last_revision(),
337 repos.generate_revision_id(2, "", "none"))
338 self.assertEqual(repos.generate_revision_id(2, "", "none"),
339 self.olddir.open_branch().last_revision())
341 def test_pull_after_push(self):
342 self.build_tree({'dc/file': 'data'})
343 wt = self.newdir.open_workingtree()
345 wt.commit(message="Commit from Bzr")
347 self.olddir.open_branch().pull(self.newdir.open_branch())
349 repos = self.olddir.find_repository()
350 inv = repos.get_inventory(repos.generate_revision_id(2, "", "none"))
351 self.assertTrue(inv.has_filename('file'))
352 self.assertEquals(wt.branch.last_revision(),
353 repos.generate_revision_id(2, "", "none"))
355 self.assertEqual(repos.generate_revision_id(2, "", "none"),
356 self.olddir.open_branch().last_revision())
358 self.newdir.open_branch().pull(self.olddir.open_branch())
360 self.assertEqual(repos.generate_revision_id(2, "", "none"),
361 self.newdir.open_branch().last_revision())
363 def test_message(self):
364 self.build_tree({'dc/file': 'data'})
365 wt = self.newdir.open_workingtree()
367 wt.commit(message="Commit from Bzr")
369 self.olddir.open_branch().pull(self.newdir.open_branch())
371 repos = self.olddir.find_repository()
372 self.assertEqual("Commit from Bzr",
374 repos.generate_revision_id(2, "", "none")).message)
376 def test_message_nordic(self):
377 self.build_tree({'dc/file': 'data'})
378 wt = self.newdir.open_workingtree()
380 wt.commit(message=u"\xe6\xf8\xe5")
382 self.olddir.open_branch().pull(self.newdir.open_branch())
384 repos = self.olddir.find_repository()
385 self.assertEqual(u"\xe6\xf8\xe5", repos.get_revision(
386 repos.generate_revision_id(2, "", "none")).message)
388 def test_commit_rename_file(self):
389 self.build_tree({'dc/vla': "data"})
390 wt = self.newdir.open_workingtree()
392 wt.set_pending_merges(["some-ghost-revision"])
393 wt.commit(message="data")
394 wt.rename_one("vla", "bar")
395 wt.commit(message="doe")
396 self.olddir.open_branch().pull(self.newdir.open_branch())
397 paths = self.client_log(self.repos_url, 3, 0)[3][0]
398 self.assertEquals('D', paths["/vla"].action)
399 self.assertEquals('A', paths["/bar"].action)
400 self.assertEquals('/vla', paths["/bar"].copyfrom_path)
401 self.assertEquals(2, paths["/bar"].copyfrom_rev)
403 def test_commit_rename_file_from_directory(self):
404 wt = self.newdir.open_workingtree()
405 self.build_tree({'dc/adir/foo': "data"})
408 wt.commit(message="data")
409 wt.rename_one("adir/foo", "bar")
410 self.assertTrue(wt.has_filename("bar"))
411 self.assertFalse(wt.has_filename("adir/foo"))
412 wt.commit(message="doe")
413 self.olddir.open_branch().pull(self.newdir.open_branch())
414 paths = self.client_log(self.repos_url, 3, 0)[3][0]
415 mutter('paths %r' % paths)
416 self.assertEquals('D', paths["/adir/foo"].action)
417 self.assertEquals('A', paths["/bar"].action)
418 self.assertEquals('/adir/foo', paths["/bar"].copyfrom_path)
419 self.assertEquals(2, paths["/bar"].copyfrom_rev)
421 def test_commit_remove(self):
422 wt = self.newdir.open_workingtree()
423 self.build_tree({'dc/foob': "data"})
425 wt.commit(message="data")
427 wt.commit(message="doe")
428 self.olddir.open_branch().pull(self.newdir.open_branch())
429 paths = self.client_log(self.repos_url, 3, 0)[3][0]
430 mutter('paths %r' % paths)
431 self.assertEquals('D', paths["/foob"].action)
433 def test_commit_rename_remove_parent(self):
434 wt = self.newdir.open_workingtree()
435 self.build_tree({'dc/adir/foob': "data"})
438 wt.commit(message="data")
439 wt.rename_one("adir/foob", "bar")
441 wt.commit(message="doe")
442 self.olddir.open_branch().pull(self.newdir.open_branch())
443 paths = self.client_log(self.repos_url, 3, 0)[3][0]
444 mutter('paths %r' % paths)
445 self.assertEquals('D', paths["/adir"].action)
446 self.assertEquals('A', paths["/bar"].action)
447 self.assertEquals('/adir/foob', paths["/bar"].copyfrom_path)
448 self.assertEquals(2, paths["/bar"].copyfrom_rev)
450 def test_commit_remove_nested(self):
451 wt = self.newdir.open_workingtree()
452 self.build_tree({'dc/adir/foob': "data"})
455 wt.commit(message="data")
456 wt.remove(["adir/foob"])
457 wt.commit(message="doe")
458 self.olddir.open_branch().pull(self.newdir.open_branch())
459 paths = self.client_log(self.repos_url, 3, 0)[3][0]
460 mutter('paths %r' % paths)
461 self.assertEquals('D', paths["/adir/foob"].action)
464 class TestPushNested(TestCaseWithSubversionRepository):
466 super(TestPushNested, self).setUp()
467 self.repos_url = self.make_client('d', 'sc')
469 self.build_tree({'sc/foo/trunk/bla': "data"})
470 self.client_add("sc/foo")
471 self.client_commit("sc", "foo")
473 self.olddir = self.open_checkout_bzrdir("sc/foo/trunk")
475 self.newdir = self.olddir.sprout("dc")
477 def test_simple(self):
478 self.build_tree({'dc/file': 'data'})
479 wt = self.newdir.open_workingtree()
481 wt.commit(message="Commit from Bzr")
482 self.olddir.open_branch().pull(self.newdir.open_branch())
483 repos = self.olddir.find_repository()
484 self.client_update("sc")
485 self.assertTrue(os.path.exists("sc/foo/trunk/file"))
486 self.assertFalse(os.path.exists("sc/foo/trunk/filel"))
489 class HeavyWeightCheckoutTests(TestCaseWithSubversionRepository):
491 repos_url = self.make_client("d", "sc")
492 master_branch = Branch.open(repos_url)
494 local_dir = master_branch.bzrdir.sprout("b")
495 wt = local_dir.open_workingtree()
496 local_dir.open_branch().bind(master_branch)
497 local_dir.open_branch().unbind()
499 def test_commit(self):
500 repos_url = self.make_client("d", "sc")
501 master_branch = Branch.open(repos_url)
503 local_dir = master_branch.bzrdir.sprout("b")
504 wt = local_dir.open_workingtree()
505 local_dir.open_branch().bind(master_branch)
506 self.build_tree({'b/file': 'data'})
508 revid = wt.commit(message="Commit from Bzr")
509 master_branch = Branch.open(repos_url)
510 self.assertEquals(revid, master_branch.last_revision())
512 def test_fileid(self):
513 repos_url = self.make_client("d", "sc")
514 master_branch = Branch.open(repos_url)
516 local_dir = master_branch.bzrdir.sprout("b")
517 wt = local_dir.open_workingtree()
518 local_dir.open_branch().bind(master_branch)
519 self.build_tree({'b/file': 'data'})
521 oldid = wt.path2id("file")
522 revid1 = wt.commit(message="Commit from Bzr")
523 wt.rename_one('file', 'file2')
524 revid2 = wt.commit(message="Commit from Bzr")
525 master_branch = Branch.open(repos_url)
526 self.assertEquals("file\t%s\n" % oldid,
527 self.client_get_prop(repos_url, "bzr:file-ids", 1))
528 self.assertEquals("file2\t%s\n" % oldid,
529 self.client_get_prop(repos_url, "bzr:file-ids", 2))
530 tree1 = master_branch.repository.revision_tree(revid1)
531 tree2 = master_branch.repository.revision_tree(revid2)
532 delta = tree2.changes_from(tree1)
533 self.assertEquals(0, len(delta.added))
534 self.assertEquals(0, len(delta.removed))
535 self.assertEquals(1, len(delta.renamed))
537 def test_nested_fileid(self):
538 repos_url = self.make_client("d", "sc")
539 master_branch = Branch.open(repos_url)
541 local_dir = master_branch.bzrdir.sprout("b")
542 wt = local_dir.open_workingtree()
543 local_dir.open_branch().bind(master_branch)
544 self.build_tree({'b/dir/file': 'data'})
547 dirid = wt.path2id("dir")
548 fileid = wt.path2id("dir/file")
549 revid1 = wt.commit(message="Commit from Bzr")
550 master_branch = Branch.open(repos_url)
551 self.assertEquals("dir\t%s\n" % dirid +
552 "dir/file\t%s\n" % fileid,
553 self.client_get_prop(repos_url, "bzr:file-ids", 1))
556 class RevpropTests(TestCaseWithSubversionRepository):
557 def test_change_revprops(self):
558 repos_url = self.make_client("d", "dc")
559 self.build_tree({"dc/foo.txt": "txt"})
560 self.client_add("dc/foo.txt")
561 self.client_commit("dc", "My commit")
563 transport = SvnRaTransport(repos_url)
564 set_svn_revprops(transport, 1, {"svn:author": "Somebody",
565 "svn:date": svn_time_to_cstring(1000000*473385600)})
567 self.assertEquals(("Somebody", "1985-01-01T00:00:00.000000Z", "My commit"),
568 self.client_log("dc")[1][1:])
570 def test_change_revprops_disallowed(self):
571 repos_url = self.make_client("d", "dc", allow_revprop_changes=False)
572 self.build_tree({"dc/foo.txt": "txt"})
573 self.client_add("dc/foo.txt")
574 self.client_commit("dc", "My commit")
576 transport = SvnRaTransport(repos_url)
577 self.assertRaises(RevpropChangeFailed,
578 lambda: set_svn_revprops(transport, 1, {"svn:author": "Somebody", "svn:date": svn_time_to_cstring(1000000*473385600)}))