1 # vim: set fileencoding=utf-8 :
4 Test L{gbp.git.GitRepository}
6 This testcase creates several repositores:
8 - A repository at L{repo_dir} called I{repo}
9 - A bare repository at L{bare_dir} called I{bare}
10 - A clone of I{repo} below L{clone_dir} called I{clone}
11 - A mirror of I{repo} below L{mirror_clone_dir} called I{mirror}
18 gbp.log.setup(color=False, verbose=True)
20 repo_dir, bare_dir, clone_dir, mirror_clone_dir = map(
21 lambda x, tmpdir=context.new_tmpdir(__name__): tmpdir.join(x),
22 ['repo', 'bare', 'clone', 'mirror_clone'])
29 - L{gbp.git.GitRepository.create}
32 - L{gbp.git.GitRepository.path}
33 - L{gbp.git.GitRepository.git_dir}
35 >>> import os, gbp.git
36 >>> repo = gbp.git.GitRepository.create(repo_dir)
37 >>> repo.path == repo_dir
39 >>> repo.git_dir == os.path.join(repo_dir, '.git')
41 >>> type(repo) == gbp.git.GitRepository
48 Empty repos have no branch
51 - L{gbp.git.GitRepository.get_branch}
52 - L{gbp.git.GitRepository.is_empty}
55 >>> repo = gbp.git.GitRepository(repo_dir)
68 - L{gbp.git.GitRepository.add_files}
69 - L{gbp.git.GitRepository.commit_all}
70 - L{gbp.git.GitRepository.is_clean}
73 - L{gbp.git.GitRepository.head}
75 >>> import gbp.git, shutil, os
76 >>> repo = gbp.git.GitRepository(repo_dir)
77 >>> shutil.copy(os.path.join(repo.path, ".git/HEAD"), \
78 os.path.join(repo.path, "testfile"))
79 >>> repo.is_clean()[0]
81 >>> repo.is_clean(ignore_untracked=True)[0]
83 >>> repo.add_files(repo.path, force=True)
84 >>> repo.commit_all(msg="foo")
85 >>> repo.is_clean()[0]
93 def test_branch_master():
95 First branch is called I{master}
98 - L{gbp.git.GitRepository.get_branch}
99 >>> import gbp.git, shutil
100 >>> repo = gbp.git.GitRepository(repo_dir)
101 >>> repo.get_branch()
109 Remove untracked files from the working tree
112 - L{gbp.git.GitRepository.clean}
114 >>> import gbp.git, shutil, os
115 >>> repo = gbp.git.GitRepository(repo_dir)
116 >>> shutil.copy(os.path.join(repo.path, ".git/HEAD"), \
117 os.path.join(repo.path, "testclean"))
118 >>> repo.clean(dry_run=True)
119 >>> repo.is_clean()[0]
121 >>> repo.clean(directories=True, force=True)
122 >>> repo.is_clean()[0]
126 def test_create_branch():
128 Create a branch name I{foo}
131 - L{gbp.git.GitRepository.create_branch}
132 - L{gbp.git.GitRepository.branch_contains}
134 >>> import gbp.git, shutil
135 >>> repo = gbp.git.GitRepository(repo_dir)
136 >>> repo.create_branch("foo")
137 >>> repo.branch_contains("foo", 'HEAD')
139 >>> repo.branch_contains("doesnotexist", 'HEAD', remote=True)
143 def test_delete_branch():
145 Create a branch named I{foo2} and delete it
148 - L{gbp.git.GitRepository.create_branch}
149 - L{gbp.git.GitRepository.delete_branch}
151 >>> import gbp.git, shutil
152 >>> repo = gbp.git.GitRepository(repo_dir)
153 >>> repo.create_branch("bar")
154 >>> repo.delete_branch("bar")
155 >>> repo.delete_branch("master")
156 Traceback (most recent call last):
158 GitRepositoryError: Can't delete the branch you're on
161 def test_set_branch():
163 Switch to branch named I{foo}
166 - L{gbp.git.GitRepository.set_branch}
167 - L{gbp.git.GitRepository.get_branch}
168 - L{gbp.git.GitRepository.branch}
171 >>> repo = gbp.git.GitRepository(repo_dir)
172 >>> repo.set_branch("foo")
173 >>> repo.get_branch() == "foo"
175 >>> repo.branch == "foo"
180 def test_rename_branch():
182 Create branch named I{baz}, rename it to I{bax} and finally delete it
185 - L{gbp.git.GitRepository.create_branch}
186 - L{gbp.git.GitRepository.rename_branch}
187 - L{gbp.git.GitRepository.delete_branch}
190 >>> repo = gbp.git.GitRepository(repo_dir)
191 >>> repo.create_branch("baz")
192 >>> repo.rename_branch("baz", "bax")
193 >>> repo.delete_branch("bax")
197 def test_set_upstream_branch():
199 Set upstream branch master -> origin/master
201 >>> import os, shutil
203 >>> repo = gbp.git.GitRepository(repo_dir)
204 >>> os.makedirs(os.path.join(repo.git_dir, 'refs/remotes/origin'))
205 >>> shutil.copy(os.path.join(repo.git_dir, 'refs/heads/master'), \
206 os.path.join(repo.git_dir, 'refs/remotes/origin/'))
207 >>> repo.add_remote_repo('origin', 'git://git.example.com/git/origin')
208 >>> repo.set_upstream_branch('master', 'origin/master')
209 >>> repo.get_upstream_branch('master')
211 >>> repo.set_upstream_branch('bla', 'origin/master')
212 Traceback (most recent call last):
213 GitRepositoryError: Branch bla doesn't exist!
214 >>> repo.set_upstream_branch('foo', 'origin/bla')
215 Traceback (most recent call last):
216 GitRepositoryError: Branch origin/bla doesn't exist!
219 def test_get_upstream_branch():
221 Get info about upstream branches set in test_set_upstream_branch
224 >>> repo = gbp.git.GitRepository(repo_dir)
225 >>> repo.get_upstream_branch('master')
227 >>> repo.get_upstream_branch('foo')
229 >>> repo.get_upstream_branch('bla')
230 Traceback (most recent call last):
231 GitRepositoryError: Branch bla doesn't exist!
236 Create a tag named I{tag} and check it's existance
239 - L{gbp.git.GitRepository.create_tag}
240 - L{gbp.git.GitRepository.verify_tag}
241 - L{gbp.git.GitRepository.has_tag}
242 - L{gbp.git.GitRepository.get_tags}
245 >>> repo = gbp.git.GitRepository(repo_dir)
246 >>> repo.create_tag("tag")
247 >>> repo.has_tag("tag")
249 >>> repo.has_tag("unknown")
251 >>> repo.create_tag("tag2", msg="foo")
252 >>> repo.has_tag("tag2")
254 >>> repo.verify_tag("tag2")
267 - L{gbp.git.GitRepository.describe}
270 >>> repo = gbp.git.GitRepository(repo_dir)
271 >>> sha = repo.rev_parse('HEAD')
272 >>> repo.describe('HEAD')
274 >>> repo.describe('HEAD', longfmt=True) == 'tag2-0-g%s' % sha[:7]
276 >>> repo.describe('HEAD', pattern='foo*')
277 Traceback (most recent call last):
279 GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
280 >>> repo.describe('HEAD', pattern='foo*', always=True) == sha[:7]
282 >>> repo.describe('HEAD', always=True, abbrev=16)
284 >>> repo.describe('HEAD', pattern='foo*', always=True, abbrev=16) == sha[:16]
286 >>> tag = repo.describe('HEAD', longfmt=True, abbrev=16) == 'tag2-0-g%s' % sha[:16]
287 >>> repo.delete_tag('tag2')
288 >>> repo.describe('HEAD', tags=True)
290 >>> repo.describe('HEAD', tags=True, exact_match=True)
292 >>> repo.create_tag('tag2', msg='foo')
300 - L{gbp.git.GitRepository.find_tag}
303 >>> repo = gbp.git.GitRepository(repo_dir)
304 >>> repo.find_tag('HEAD')
306 >>> repo.find_tag('HEAD', pattern='foo*')
307 Traceback (most recent call last):
309 GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
317 - L{gbp.git.GitRepository.move_tag}
318 - L{gbp.git.GitRepository.has_tag}
321 >>> repo = gbp.git.GitRepository(repo_dir)
322 >>> repo.move_tag("tag", "moved")
323 >>> repo.has_tag("tag")
325 >>> repo.has_tag("moved")
329 def test_delete_tag():
334 - L{gbp.git.GitRepository.delete_tag}
335 - L{gbp.git.GitRepository.has_tag}
338 >>> repo = gbp.git.GitRepository(repo_dir)
339 >>> repo.has_tag("moved")
341 >>> repo.delete_tag("moved")
342 >>> repo.has_tag("moved")
346 def test_get_obj_type():
348 Find commit SHA1 related to tags
351 - L{gbp.git.GitRepository.create_tag}
352 - L{gbp.git.GitRepository.get_obj_type}
353 - L{gbp.git.GitRepository.delete_tag}
356 >>> repo = gbp.git.GitRepository(repo_dir)
357 >>> repo.create_tag("tag3", "tag msg")
358 >>> repo.get_obj_type("tag3")
360 >>> repo.get_obj_type("HEAD")
362 >>> repo.get_obj_type("HEAD:testfile")
364 >>> repo.delete_tag("tag3")
367 def test_list_files():
369 List files in the index
372 - L{gbp.git.GitRepository.list_files}
373 - L{gbp.git.GitRepository.add_files}
374 - L{gbp.git.GitRepository.commit_staged}
375 - L{gbp.git.GitRepository.commit_files}
376 - L{gbp.git.GitRepository.force_head}
378 >>> import gbp.git, os, shutil
379 >>> repo = gbp.git.GitRepository(repo_dir)
380 >>> src = os.path.join(repo.path, ".git/HEAD")
381 >>> dst = os.path.join(repo.path, "testfile")
382 >>> repo.list_files()
384 >>> repo.list_files(['modified'])
386 >>> repo.list_files(['modified', 'deleted'])
388 >>> repo.list_files(['modified', 'deleted', 'cached'])
390 >>> shutil.copy(src, dst)
391 >>> repo.list_files(['modified'])
393 >>> repo.add_files(dst)
394 >>> repo.commit_staged(msg="foo")
395 >>> repo.list_files(['modified'])
397 >>> repo.list_files(['foo'])
398 Traceback (most recent call last):
400 GitRepositoryError: Unknown type 'foo'
401 >>> repo.force_head('HEAD^', hard=True)
402 >>> repo.list_files(['modified'])
404 >>> shutil.copy(src, dst)
405 >>> repo.list_files(['modified'])
407 >>> repo.commit_files(dst, msg="foo")
408 >>> repo.list_files(['modified'])
412 def test_get_commits():
417 - L{gbp.git.GitRepository.get_commits}
420 >>> repo = gbp.git.GitRepository(repo_dir)
421 >>> commits = repo.get_commits()
422 >>> type(commits) == list and len(commits) == 2
424 >>> len(repo.get_commits(num=1)) == 1
426 >>> commits2 = repo.get_commits(since='HEAD~1')
427 >>> len(commits2) == 1
429 >>> commits2[0] == commits[0]
431 >>> commits2 = repo.get_commits(until='HEAD~1')
432 >>> len(commits2) == 1
434 >>> commits2[0] == commits[-1]
436 >>> repo.get_commits(paths=['foo', 'bar'])
438 >>> repo.get_commits(paths=['testfile']) == commits
443 def test_get_commit_info():
445 Test inspecting commits
448 - L{gbp.git.GitRepository.get_commit_info}
451 >>> from datetime import datetime
452 >>> repo = gbp.git.GitRepository(repo_dir)
453 >>> info = repo.get_commit_info('HEAD')
460 >>> '@' in info['author'].email
462 >>> '@' in info['committer'].email
464 >>> now = datetime.now()
465 >>> (now - datetime.fromtimestamp(int(info['author'].date.split()[0]))).seconds < 10
467 >>> (now - datetime.fromtimestamp(int(info['committer'].date.split()[0]))).seconds < 10
469 >>> info['patchname']
472 defaultdict(<type 'list'>, {'M': ['testfile']})
473 >>> repo.get_subject('HEAD')
482 - L{gbp.git.GitRepository.diff}
485 >>> repo = gbp.git.GitRepository(repo_dir)
486 >>> len(repo.diff('HEAD~1', 'HEAD')) > 3
488 >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile')) > 3
490 >>> len(repo.diff('HEAD~1', 'HEAD', 'filenotexist')) == 0
494 def test_mirror_clone():
499 - L{gbp.git.GitRepository.clone}
500 - L{gbp.git.GitRepository.is_empty}
501 - L{gbp.git.GitRepository.set_branch}
502 - L{gbp.git.GitRepository.has_branch}
503 - L{gbp.git.GitRepository.branch}
506 >>> repo = gbp.git.GitRepository(repo_dir)
507 >>> repo.set_branch('master')
508 >>> mirror = gbp.git.GitRepository.clone(mirror_clone_dir, repo.path, mirror=True)
509 >>> mirror.is_empty()
513 >>> mirror.has_branch('foo')
515 >>> mirror.has_branch('bar')
517 >>> mirror.set_branch('foo')
520 >>> mirror.force_head('foo^')
528 - L{gbp.git.GitRepository.clone}
529 - L{gbp.git.GitRepository.is_empty}
530 - L{gbp.git.GitRepository.set_branch}
531 - L{gbp.git.GitRepository.branch}
532 - L{gbp.git.GitRepository.get_merge_branch}
533 - L{gbp.git.GitRepository.get_remote_branches}
534 - L{gbp.git.GitRepository.get_local_branches}
535 - L{gbp.git.GitRepository.get_remote_repos}
536 - L{gbp.git.GitRepository.has_remote_repo}
539 >>> repo = gbp.git.GitRepository(repo_dir)
540 >>> repo.set_branch('master')
541 >>> clone = gbp.git.GitRepository.clone(clone_dir, repo.path)
546 >>> clone.get_remote_branches()
547 ['origin/HEAD', 'origin/foo', 'origin/master']
548 >>> clone.get_local_branches()
550 >>> clone.get_merge_branch('master')
552 >>> clone.create_branch('foo', 'origin/foo')
553 >>> clone.get_merge_branch('foo')
555 >>> clone.create_branch('bar')
556 >>> clone.get_merge_branch('bar') # None if no merge branch exists
557 >>> clone.get_local_branches()
558 ['bar', 'foo', 'master']
559 >>> clone.get_remote_repos()
561 >>> clone.has_remote_repo('origin')
563 >>> clone.has_branch('origin/master', remote=True)
565 >>> clone.has_remote_repo('godiug')
574 - L{gbp.git.GitRepository.merge}
575 - L{gbp.git.GitRepository.set_branch}
578 >>> repo = gbp.git.GitRepository(repo_dir)
579 >>> repo.set_branch('master')
580 >>> repo.merge('foo')
585 Pull from a remote repository
588 - L{gbp.git.GitRepository.set_branch}
589 - L{gbp.git.GitRepository.pull}
591 >>> import gbp.git, os
592 >>> d = os.path.join(clone_dir, 'repo')
593 >>> clone = gbp.git.GitRepository(d)
594 >>> clone.set_branch('master')
600 Fetch from a remote repository
603 - L{gbp.git.GitRepository.fetch}
604 - L{gbp.git.GitRepository.push}
605 - L{gbp.git.GitRepository.push_tag}
606 - L{gbp.git.GitRepository.add_remote_repo}
607 - L{gbp.git.GitRepository.remove_remote_repo}
609 >>> import gbp.git, os
610 >>> d = os.path.join(clone_dir, 'repo')
611 >>> clone = gbp.git.GitRepository(d)
614 >>> clone.push('origin')
615 >>> clone.push('origin', 'master')
616 >>> clone.create_tag('tag3')
617 >>> clone.push_tag('origin', 'tag3')
618 >>> clone.add_remote_repo('foo', repo_dir)
619 >>> clone.fetch('foo')
620 >>> clone.fetch('foo', tags=True)
621 >>> clone.fetch('foo', refspec='refs/heads/master')
622 >>> clone.fetch(all_remotes=True)
623 >>> clone.remove_remote_repo('foo')
626 def test_create_bare():
628 Create a bare repository
631 - L{gbp.git.GitRepository.create}
632 - L{gbp.git.GitRepository.is_empty}
635 >>> bare = gbp.git.GitRepository.create(bare_dir, bare=True, description="msg")
636 >>> bare.path == bare_dir
638 >>> bare.git_dir[:-1] == bare_dir
640 >>> type(bare) == gbp.git.GitRepository
648 def test_nonexistant():
650 Check that accessing a non existant repository fails.
653 - L{gbp.git.GitRepository.__init__}
656 >>> bare = gbp.git.GitRepository("/does/not/exist")
657 Traceback (most recent call last):
659 GitRepositoryError: No Git repository at '/does/not/exist'
662 def test_create_noperm():
664 Check that creating a repository at a path that isn't writeable fails
667 - L{gbp.git.GitRepository.create}
670 >>> gbp.git.GitRepository.create("/does/not/exist")
671 Traceback (most recent call last):
673 GitRepositoryError: Cannot create Git repository at '/does/not/exist': Permission denied
681 - L{gbp.git.GitRepository.checkout}
682 - L{gbp.git.GitRepository.get_branch}
683 - L{gbp.git.GitRepository.set_branch}
684 - L{gbp.git.GitRepository.rev_parse}
687 - L{gbp.git.GitRepository.branch}
688 - L{gbp.git.GitRepository.tags}
691 >>> repo = gbp.git.GitRepository(repo_dir)
692 >>> repo.checkout('master')
695 >>> repo.rev_parse('doesnotexist')
696 Traceback (most recent call last):
698 GitRepositoryError: revision 'doesnotexist' not found
699 >>> sha1 = repo.rev_parse('master', short=10)
702 >>> sha1 = repo.rev_parse('master')
705 >>> repo.checkout(sha1)
707 >>> repo.get_branch()
708 Traceback (most recent call last):
710 GitRepositoryError: Currently not on a branch
711 >>> tag = repo.tags[0]
712 >>> repo.checkout(tag)
718 Test garbace collection
721 - L{gbp.git.GitRepository.collect_garbage}
724 >>> repo = gbp.git.GitRepository(repo_dir)
725 >>> repo.collect_garbage()
730 Test grepping through commit messages
733 - L{gbp.git.GitRepository.grep_log}
736 >>> repo = gbp.git.GitRepository(repo_dir)
737 >>> repo.set_branch('master')
738 >>> len(repo.grep_log('foo')) == 2
740 >>> len(repo.grep_log('foo', 'master')) == 2
742 >>> repo.grep_log('blafasel')
744 >>> repo.grep_log('foo', 'doesnotexist')
745 Traceback (most recent call last):
747 GitRepositoryError: Error grepping log for foo: fatal: bad revision 'doesnotexist'
752 Test if branch is fast forwardable
755 - L{gbp.git.GitRepository.is_fast_forward}
758 >>> repo = gbp.git.GitRepository(repo_dir)
759 >>> repo.is_fast_forward('master', 'foo')
761 >>> repo.create_branch('ff', 'HEAD^')
762 >>> repo.is_fast_forward('ff', 'master')
764 >>> repo.is_fast_forward('master', 'ff')
768 def test_update_ref():
770 Test updating a reference
773 - L{gbp.git.GitRepository.update_ref}
775 >>> import gbp.git, os
776 >>> repo = gbp.git.GitRepository(repo_dir)
777 >>> repo.update_ref('new_ref', 'master', msg='update')
778 >>> os.path.exists(os.path.join(repo.git_dir, 'new_ref'))
783 def test_make_tree():
788 - L{gbp.git.GitRepository.write_file}
789 - L{gbp.git.GitRepository.list_tree}
790 - L{gbp.git.GitRepository.make_tree}
793 >>> repo = gbp.git.GitRepository(repo_dir)
794 >>> sha1 = repo.write_file('testfile')
796 '19af7398c894bc5e86e17259317e4db519e9241f'
797 >>> head = repo.list_tree('HEAD')
799 [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
800 >>> head.append(['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile2'])
801 >>> repo.make_tree(head)
802 '745951810c9e22fcc6de9b23f05efd6ab5512123'
806 def test_update_submodules():
808 Updating submodules if we don't have any is a noop
811 - L{gbp.git.GitRepository.has_submodules}
812 - L{gbp.git.GitRepository.update_submodules}
815 >>> repo = gbp.git.GitRepository(repo_dir)
816 >>> repo.has_submodules()
818 >>> repo.update_submodules()
821 def test_get_merge_base():
823 Find the common ancestor of two objects
826 - L{gbp.git.GitRepository.get_merge_base}
829 >>> repo = gbp.git.GitRepository(repo_dir)
830 >>> sha1 = repo.get_merge_base('master', 'foo')
833 >>> repo.get_merge_base('master', 'doesnotexist')
834 Traceback (most recent call last):
836 GitRepositoryError: Failed to get common ancestor: fatal: Not a valid object name doesnotexist
839 def test_cmd_has_feature():
842 - L{gbp.git.GitRepository._cmd_has_feature}
845 >>> repo = gbp.git.GitRepository(repo_dir)
846 >>> repo._cmd_has_feature("commit", "a")
848 >>> repo._cmd_has_feature("commit", "reuse-message")
850 >>> repo._cmd_has_feature("merge", "n")
852 >>> repo._cmd_has_feature("merge", "stat")
854 >>> repo._cmd_has_feature("format-patch", "cc")
856 >>> repo._cmd_has_feature("merge", "foobaroption")
858 >>> repo._cmd_has_feature("foobarcmd", "foobaroption")
859 Traceback (most recent call last):
861 GitRepositoryError: Invalid git command 'foobarcmd': No manual entry for gitfoobarcmd
862 >>> repo._cmd_has_feature("show", "standard-notes")
864 >>> repo._cmd_has_feature("show", "no-standard-notes")
872 >>> context.teardown()
875 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: