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()
108 def test_create_branch():
110 Create a branch name I{foo}
113 - L{gbp.git.GitRepository.create_branch}
114 - L{gbp.git.GitRepository.branch_contains}
116 >>> import gbp.git, shutil
117 >>> repo = gbp.git.GitRepository(repo_dir)
118 >>> repo.create_branch("foo")
119 >>> repo.branch_contains("foo", 'HEAD')
121 >>> repo.branch_contains("doesnotexist", 'HEAD', remote=True)
125 def test_delete_branch():
127 Create a branch named I{foo2} and delete it
130 - L{gbp.git.GitRepository.create_branch}
131 - L{gbp.git.GitRepository.delete_branch}
133 >>> import gbp.git, shutil
134 >>> repo = gbp.git.GitRepository(repo_dir)
135 >>> repo.create_branch("bar")
136 >>> repo.delete_branch("bar")
137 >>> repo.delete_branch("master")
138 Traceback (most recent call last):
140 GitRepositoryError: Can't delete the branch you're on
143 def test_set_branch():
145 Switch to branch named I{foo}
148 - L{gbp.git.GitRepository.set_branch}
149 - L{gbp.git.GitRepository.get_branch}
150 - L{gbp.git.GitRepository.branch}
153 >>> repo = gbp.git.GitRepository(repo_dir)
154 >>> repo.set_branch("foo")
155 >>> repo.get_branch() == "foo"
157 >>> repo.branch == "foo"
162 def test_rename_branch():
164 Create branch named I{baz}, rename it to I{bax} and finally delete it
167 - L{gbp.git.GitRepository.create_branch}
168 - L{gbp.git.GitRepository.rename_branch}
169 - L{gbp.git.GitRepository.delete_branch}
172 >>> repo = gbp.git.GitRepository(repo_dir)
173 >>> repo.create_branch("baz")
174 >>> repo.rename_branch("baz", "bax")
175 >>> repo.delete_branch("bax")
179 def test_set_upstream_branch():
181 Set upstream branch master -> origin/master
183 >>> import os, shutil
185 >>> repo = gbp.git.GitRepository(repo_dir)
186 >>> os.makedirs(os.path.join(repo.git_dir, 'refs/remotes/origin'))
187 >>> shutil.copy(os.path.join(repo.git_dir, 'refs/heads/master'), \
188 os.path.join(repo.git_dir, 'refs/remotes/origin/'))
189 >>> repo.add_remote_repo('origin', 'git://git.example.com/git/origin')
190 >>> repo.set_upstream_branch('master', 'origin/master')
191 >>> repo.get_upstream_branch('master')
193 >>> repo.set_upstream_branch('bla', 'origin/master')
194 Traceback (most recent call last):
195 GitRepositoryError: Branch bla doesn't exist!
196 >>> repo.set_upstream_branch('foo', 'origin/bla')
197 Traceback (most recent call last):
198 GitRepositoryError: Branch origin/bla doesn't exist!
201 def test_get_upstream_branch():
203 Get info about upstream branches set in test_set_upstream_branch
206 >>> repo = gbp.git.GitRepository(repo_dir)
207 >>> repo.get_upstream_branch('master')
209 >>> repo.get_upstream_branch('foo')
211 >>> repo.get_upstream_branch('bla')
212 Traceback (most recent call last):
213 GitRepositoryError: Branch bla doesn't exist!
218 Create a tag named I{tag} and check it's existance
221 - L{gbp.git.GitRepository.create_tag}
222 - L{gbp.git.GitRepository.verify_tag}
223 - L{gbp.git.GitRepository.has_tag}
224 - L{gbp.git.GitRepository.get_tags}
227 >>> repo = gbp.git.GitRepository(repo_dir)
228 >>> repo.create_tag("tag")
229 >>> repo.has_tag("tag")
231 >>> repo.has_tag("unknown")
233 >>> repo.create_tag("tag2", msg="foo")
234 >>> repo.has_tag("tag2")
236 >>> repo.verify_tag("tag2")
249 - L{gbp.git.GitRepository.describe}
252 >>> repo = gbp.git.GitRepository(repo_dir)
253 >>> sha = repo.rev_parse('HEAD')
254 >>> repo.describe('HEAD')
256 >>> repo.describe('HEAD', longfmt=True) == 'tag2-0-g%s' % sha[:7]
258 >>> repo.describe('HEAD', pattern='foo*')
259 Traceback (most recent call last):
261 GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
262 >>> repo.describe('HEAD', pattern='foo*', always=True) == sha[:7]
264 >>> repo.describe('HEAD', always=True, abbrev=16)
266 >>> repo.describe('HEAD', pattern='foo*', always=True, abbrev=16) == sha[:16]
268 >>> tag = repo.describe('HEAD', longfmt=True, abbrev=16) == 'tag2-0-g%s' % sha[:16]
269 >>> repo.delete_tag('tag2')
270 >>> repo.describe('HEAD', tags=True)
272 >>> repo.describe('HEAD', tags=True, exact_match=True)
274 >>> repo.create_tag('tag2', msg='foo')
282 - L{gbp.git.GitRepository.find_tag}
285 >>> repo = gbp.git.GitRepository(repo_dir)
286 >>> repo.find_tag('HEAD')
288 >>> repo.find_tag('HEAD', pattern='foo*')
289 Traceback (most recent call last):
291 GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
299 - L{gbp.git.GitRepository.move_tag}
300 - L{gbp.git.GitRepository.has_tag}
303 >>> repo = gbp.git.GitRepository(repo_dir)
304 >>> repo.move_tag("tag", "moved")
305 >>> repo.has_tag("tag")
307 >>> repo.has_tag("moved")
311 def test_delete_tag():
316 - L{gbp.git.GitRepository.delete_tag}
317 - L{gbp.git.GitRepository.has_tag}
320 >>> repo = gbp.git.GitRepository(repo_dir)
321 >>> repo.has_tag("moved")
323 >>> repo.delete_tag("moved")
324 >>> repo.has_tag("moved")
328 def test_get_obj_type():
330 Find commit SHA1 related to tags
333 - L{gbp.git.GitRepository.create_tag}
334 - L{gbp.git.GitRepository.get_obj_type}
335 - L{gbp.git.GitRepository.delete_tag}
338 >>> repo = gbp.git.GitRepository(repo_dir)
339 >>> repo.create_tag("tag3", "tag msg")
340 >>> repo.get_obj_type("tag3")
342 >>> repo.get_obj_type("HEAD")
344 >>> repo.get_obj_type("HEAD:testfile")
346 >>> repo.delete_tag("tag3")
349 def test_list_files():
351 List files in the index
354 - L{gbp.git.GitRepository.list_files}
355 - L{gbp.git.GitRepository.add_files}
356 - L{gbp.git.GitRepository.commit_staged}
357 - L{gbp.git.GitRepository.commit_files}
358 - L{gbp.git.GitRepository.force_head}
360 >>> import gbp.git, os, shutil
361 >>> repo = gbp.git.GitRepository(repo_dir)
362 >>> src = os.path.join(repo.path, ".git/HEAD")
363 >>> dst = os.path.join(repo.path, "testfile")
364 >>> repo.list_files()
366 >>> repo.list_files(['modified'])
368 >>> repo.list_files(['modified', 'deleted'])
370 >>> repo.list_files(['modified', 'deleted', 'cached'])
372 >>> shutil.copy(src, dst)
373 >>> repo.list_files(['modified'])
375 >>> repo.add_files(dst)
376 >>> repo.commit_staged(msg="foo")
377 >>> repo.list_files(['modified'])
379 >>> repo.list_files(['foo'])
380 Traceback (most recent call last):
382 GitRepositoryError: Unknown type 'foo'
383 >>> repo.force_head('HEAD^', hard=True)
384 >>> repo.list_files(['modified'])
386 >>> shutil.copy(src, dst)
387 >>> repo.list_files(['modified'])
389 >>> repo.commit_files(dst, msg="foo")
390 >>> repo.list_files(['modified'])
394 def test_get_commits():
399 - L{gbp.git.GitRepository.get_commits}
402 >>> repo = gbp.git.GitRepository(repo_dir)
403 >>> commits = repo.get_commits()
404 >>> type(commits) == list and len(commits) == 2
406 >>> len(repo.get_commits(num=1)) == 1
408 >>> commits2 = repo.get_commits(since='HEAD~1')
409 >>> len(commits2) == 1
411 >>> commits2[0] == commits[0]
413 >>> commits2 = repo.get_commits(until='HEAD~1')
414 >>> len(commits2) == 1
416 >>> commits2[0] == commits[-1]
418 >>> repo.get_commits(paths=['foo', 'bar'])
420 >>> repo.get_commits(paths=['testfile']) == commits
425 def test_get_commit_info():
427 Test inspecting commits
430 - L{gbp.git.GitRepository.get_commit_info}
433 >>> from datetime import datetime
434 >>> repo = gbp.git.GitRepository(repo_dir)
435 >>> info = repo.get_commit_info('HEAD')
442 >>> '@' in info['author'].email
444 >>> '@' in info['committer'].email
446 >>> now = datetime.now()
447 >>> (now - datetime.fromtimestamp(int(info['author'].date.split()[0]))).seconds < 10
449 >>> (now - datetime.fromtimestamp(int(info['committer'].date.split()[0]))).seconds < 10
451 >>> info['patchname']
454 defaultdict(<type 'list'>, {'M': ['testfile']})
455 >>> repo.get_subject('HEAD')
464 - L{gbp.git.GitRepository.diff}
467 >>> repo = gbp.git.GitRepository(repo_dir)
468 >>> len(repo.diff('HEAD~1', 'HEAD')) > 3
470 >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile')) > 3
472 >>> len(repo.diff('HEAD~1', 'HEAD', 'filenotexist')) == 0
476 def test_mirror_clone():
481 - L{gbp.git.GitRepository.clone}
482 - L{gbp.git.GitRepository.is_empty}
483 - L{gbp.git.GitRepository.set_branch}
484 - L{gbp.git.GitRepository.has_branch}
485 - L{gbp.git.GitRepository.branch}
488 >>> repo = gbp.git.GitRepository(repo_dir)
489 >>> repo.set_branch('master')
490 >>> mirror = gbp.git.GitRepository.clone(mirror_clone_dir, repo.path, mirror=True)
491 >>> mirror.is_empty()
495 >>> mirror.has_branch('foo')
497 >>> mirror.has_branch('bar')
499 >>> mirror.set_branch('foo')
502 >>> mirror.force_head('foo^')
510 - L{gbp.git.GitRepository.clone}
511 - L{gbp.git.GitRepository.is_empty}
512 - L{gbp.git.GitRepository.set_branch}
513 - L{gbp.git.GitRepository.branch}
514 - L{gbp.git.GitRepository.get_merge_branch}
515 - L{gbp.git.GitRepository.get_remote_branches}
516 - L{gbp.git.GitRepository.get_local_branches}
517 - L{gbp.git.GitRepository.get_remote_repos}
518 - L{gbp.git.GitRepository.has_remote_repo}
521 >>> repo = gbp.git.GitRepository(repo_dir)
522 >>> repo.set_branch('master')
523 >>> clone = gbp.git.GitRepository.clone(clone_dir, repo.path)
528 >>> clone.get_remote_branches()
529 ['origin/HEAD', 'origin/foo', 'origin/master']
530 >>> clone.get_local_branches()
532 >>> clone.get_merge_branch('master')
534 >>> clone.create_branch('foo', 'origin/foo')
535 >>> clone.get_merge_branch('foo')
537 >>> clone.create_branch('bar')
538 >>> clone.get_merge_branch('bar') # None if no merge branch exists
539 >>> clone.get_local_branches()
540 ['bar', 'foo', 'master']
541 >>> clone.get_remote_repos()
543 >>> clone.has_remote_repo('origin')
545 >>> clone.has_branch('origin/master', remote=True)
547 >>> clone.has_remote_repo('godiug')
556 - L{gbp.git.GitRepository.merge}
557 - L{gbp.git.GitRepository.set_branch}
560 >>> repo = gbp.git.GitRepository(repo_dir)
561 >>> repo.set_branch('master')
562 >>> repo.merge('foo')
567 Pull from a remote repository
570 - L{gbp.git.GitRepository.set_branch}
571 - L{gbp.git.GitRepository.pull}
573 >>> import gbp.git, os
574 >>> d = os.path.join(clone_dir, 'repo')
575 >>> clone = gbp.git.GitRepository(d)
576 >>> clone.set_branch('master')
582 Fetch from a remote repository
585 - L{gbp.git.GitRepository.fetch}
586 - L{gbp.git.GitRepository.push}
587 - L{gbp.git.GitRepository.push_tag}
588 - L{gbp.git.GitRepository.add_remote_repo}
589 - L{gbp.git.GitRepository.remove_remote_repo}
591 >>> import gbp.git, os
592 >>> d = os.path.join(clone_dir, 'repo')
593 >>> clone = gbp.git.GitRepository(d)
596 >>> clone.push('origin')
597 >>> clone.push('origin', 'master')
598 >>> clone.create_tag('tag3')
599 >>> clone.push_tag('origin', 'tag3')
600 >>> clone.add_remote_repo('foo', repo_dir)
601 >>> clone.fetch('foo')
602 >>> clone.fetch('foo', tags=True)
603 >>> clone.fetch('foo', refspec='refs/heads/master')
604 >>> clone.fetch(all_remotes=True)
605 >>> clone.remove_remote_repo('foo')
608 def test_create_bare():
610 Create a bare repository
613 - L{gbp.git.GitRepository.create}
614 - L{gbp.git.GitRepository.is_empty}
617 >>> bare = gbp.git.GitRepository.create(bare_dir, bare=True, description="msg")
618 >>> bare.path == bare_dir
620 >>> bare.git_dir[:-1] == bare_dir
622 >>> type(bare) == gbp.git.GitRepository
630 def test_nonexistant():
632 Check that accessing a non existant repository fails.
635 - L{gbp.git.GitRepository.__init__}
638 >>> bare = gbp.git.GitRepository("/does/not/exist")
639 Traceback (most recent call last):
641 GitRepositoryError: No Git repository at '/does/not/exist'
644 def test_create_noperm():
646 Check that creating a repository at a path that isn't writeable fails
649 - L{gbp.git.GitRepository.create}
652 >>> gbp.git.GitRepository.create("/does/not/exist")
653 Traceback (most recent call last):
655 GitRepositoryError: Cannot create Git repository at '/does/not/exist': Permission denied
663 - L{gbp.git.GitRepository.checkout}
664 - L{gbp.git.GitRepository.get_branch}
665 - L{gbp.git.GitRepository.set_branch}
666 - L{gbp.git.GitRepository.rev_parse}
669 - L{gbp.git.GitRepository.branch}
670 - L{gbp.git.GitRepository.tags}
673 >>> repo = gbp.git.GitRepository(repo_dir)
674 >>> repo.checkout('master')
677 >>> repo.rev_parse('doesnotexist')
678 Traceback (most recent call last):
680 GitRepositoryError: revision 'doesnotexist' not found
681 >>> sha1 = repo.rev_parse('master', short=10)
684 >>> sha1 = repo.rev_parse('master')
687 >>> repo.checkout(sha1)
689 >>> repo.get_branch()
690 Traceback (most recent call last):
692 GitRepositoryError: Currently not on a branch
693 >>> tag = repo.tags[0]
694 >>> repo.checkout(tag)
700 Test garbace collection
703 - L{gbp.git.GitRepository.collect_garbage}
706 >>> repo = gbp.git.GitRepository(repo_dir)
707 >>> repo.collect_garbage()
712 Test grepping through commit messages
715 - L{gbp.git.GitRepository.grep_log}
718 >>> repo = gbp.git.GitRepository(repo_dir)
719 >>> repo.set_branch('master')
720 >>> len(repo.grep_log('foo')) == 2
722 >>> len(repo.grep_log('foo', 'master')) == 2
724 >>> repo.grep_log('blafasel')
726 >>> repo.grep_log('foo', 'doesnotexist')
727 Traceback (most recent call last):
729 GitRepositoryError: Error grepping log for foo: fatal: bad revision 'doesnotexist'
734 Test if branch is fast forwardable
737 - L{gbp.git.GitRepository.is_fast_forward}
740 >>> repo = gbp.git.GitRepository(repo_dir)
741 >>> repo.is_fast_forward('master', 'foo')
743 >>> repo.create_branch('ff', 'HEAD^')
744 >>> repo.is_fast_forward('ff', 'master')
746 >>> repo.is_fast_forward('master', 'ff')
750 def test_update_ref():
752 Test updating a reference
755 - L{gbp.git.GitRepository.update_ref}
757 >>> import gbp.git, os
758 >>> repo = gbp.git.GitRepository(repo_dir)
759 >>> repo.update_ref('new_ref', 'master', msg='update')
760 >>> os.path.exists(os.path.join(repo.git_dir, 'new_ref'))
765 def test_make_tree():
770 - L{gbp.git.GitRepository.write_file}
771 - L{gbp.git.GitRepository.list_tree}
772 - L{gbp.git.GitRepository.make_tree}
775 >>> repo = gbp.git.GitRepository(repo_dir)
776 >>> sha1 = repo.write_file('testfile')
778 '19af7398c894bc5e86e17259317e4db519e9241f'
779 >>> head = repo.list_tree('HEAD')
781 [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
782 >>> head.append(['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile2'])
783 >>> repo.make_tree(head)
784 '745951810c9e22fcc6de9b23f05efd6ab5512123'
788 def test_update_submodules():
790 Updating submodules if we don't have any is a noop
793 - L{gbp.git.GitRepository.has_submodules}
794 - L{gbp.git.GitRepository.update_submodules}
797 >>> repo = gbp.git.GitRepository(repo_dir)
798 >>> repo.has_submodules()
800 >>> repo.update_submodules()
803 def test_get_merge_base():
805 Find the common ancestor of two objects
808 - L{gbp.git.GitRepository.get_merge_base}
811 >>> repo = gbp.git.GitRepository(repo_dir)
812 >>> sha1 = repo.get_merge_base('master', 'foo')
815 >>> repo.get_merge_base('master', 'doesnotexist')
816 Traceback (most recent call last):
818 GitRepositoryError: Failed to get common ancestor: fatal: Not a valid object name doesnotexist
821 def test_cmd_has_feature():
824 - L{gbp.git.GitRepository._cmd_has_feature}
827 >>> repo = gbp.git.GitRepository(repo_dir)
828 >>> repo._cmd_has_feature("commit", "a")
830 >>> repo._cmd_has_feature("commit", "reuse-message")
832 >>> repo._cmd_has_feature("merge", "n")
834 >>> repo._cmd_has_feature("merge", "stat")
836 >>> repo._cmd_has_feature("format-patch", "cc")
838 >>> repo._cmd_has_feature("merge", "foobaroption")
840 >>> repo._cmd_has_feature("foobarcmd", "foobaroption")
841 Traceback (most recent call last):
843 GitRepositoryError: Invalid git command 'foobarcmd': No manual entry for gitfoobarcmd
844 >>> repo._cmd_has_feature("show", "standard-notes")
846 >>> repo._cmd_has_feature("show", "no-standard-notes")
854 >>> context.teardown()
857 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: