porting code to python3.x with os patch
[tools/git-buildpackage.git] / tests / test_GitRepository.py
1 # vim: set fileencoding=utf-8 :
2
3 """
4 Test L{gbp.git.GitRepository}
5
6 This testcase creates several repositores:
7
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}
12 """
13
14 from . import context
15
16 import gbp.log
17
18 gbp.log.setup(color=False, verbose=True)
19
20 repo_dir, bare_dir, clone_dir, mirror_clone_dir = list(map(
21     lambda x, tmpdir=context.new_tmpdir(__name__): tmpdir.join(x),
22     ['repo', 'bare', 'clone', 'mirror_clone']))
23
24 def test_create():
25     """
26     Create a repository
27
28     Methods tested:
29          - L{gbp.git.GitRepository.create}
30
31     Properties tested:
32          - L{gbp.git.GitRepository.path}
33          - L{gbp.git.GitRepository.git_dir}
34
35     >>> import os, gbp.git
36     >>> repo = gbp.git.GitRepository.create(repo_dir)
37     >>> repo.path == repo_dir
38     True
39     >>> repo.git_dir == os.path.join(repo_dir, '.git')
40     True
41     >>> type(repo) == gbp.git.GitRepository
42     True
43     """
44
45
46 def test_empty():
47     """
48     Empty repos have no branch
49
50     Methods tested:
51          - L{gbp.git.GitRepository.get_branch}
52          - L{gbp.git.GitRepository.is_empty}
53
54     >>> import gbp.git
55     >>> repo = gbp.git.GitRepository(repo_dir)
56     >>> repo.get_branch()
57     >>> repo.branch
58     >>> repo.is_empty()
59     True
60     """
61
62
63 def test_add_files():
64     """
65     Add some dummy data
66
67     Methods tested:
68          - L{gbp.git.GitRepository.add_files}
69          - L{gbp.git.GitRepository.commit_all}
70          - L{gbp.git.GitRepository.is_clean}
71          - L{gbp.git.GitRepository.status}
72
73     Properties tested:
74          - L{gbp.git.GitRepository.head}
75
76     >>> import gbp.git, shutil, os
77     >>> repo = gbp.git.GitRepository(repo_dir)
78     >>> shutil.copy(os.path.join(repo.path, ".git/HEAD"), \
79                                  os.path.join(repo.path, "testfile"))
80     >>> repo.is_clean()[0]
81     False
82     >>> repo.is_clean(ignore_untracked=True)[0]
83     True
84     >>> repo.add_files('testfile', force=True, untracked=False)
85     >>> list(repo.status().items())
86     [('??', ['testfile'])]
87     >>> repo.add_files(repo.path, force=True)
88     >>> list(repo.status().items())
89     [('A ', ['testfile'])]
90     >>> repo.commit_all(msg="foo")
91     >>> repo.is_clean()[0]
92     True
93     >>> h = repo.head
94     >>> len(h)
95     40
96     """
97
98
99 def test_branch_master():
100     """
101     First branch is called I{master}
102
103     Methods tested:
104          - L{gbp.git.GitRepository.get_branch}
105     >>> import gbp.git, shutil
106     >>> repo = gbp.git.GitRepository(repo_dir)
107     >>> repo.get_branch()
108     'master'
109     >>> repo.branch
110     'master'
111     """
112
113 def test_clean():
114     """
115     Remove untracked files from the working tree
116
117     Methods tested:
118          - L{gbp.git.GitRepository.clean}
119
120     >>> import gbp.git, shutil, os
121     >>> repo = gbp.git.GitRepository(repo_dir)
122     >>> shutil.copy(os.path.join(repo.path, ".git/HEAD"), \
123                                  os.path.join(repo.path, "testclean"))
124     >>> repo.clean(dry_run=True)
125     >>> repo.is_clean()[0]
126     False
127     >>> repo.clean(directories=True, force=True)
128     >>> repo.is_clean()[0]
129     True
130     """
131
132 def test_create_branch():
133     """
134     Create a branch name I{foo}
135
136     Methods tested:
137          - L{gbp.git.GitRepository.create_branch}
138          - L{gbp.git.GitRepository.branch_contains}
139
140     >>> import gbp.git, shutil
141     >>> repo = gbp.git.GitRepository(repo_dir)
142     >>> repo.create_branch("foo")
143     >>> repo.branch_contains("foo", 'HEAD')
144     True
145     >>> repo.branch_contains("doesnotexist", 'HEAD', remote=True)
146     False
147     """
148
149 def test_delete_branch():
150     """
151     Create a branch named I{foo2} and delete it
152
153     Methods tested:
154          - L{gbp.git.GitRepository.create_branch}
155          - L{gbp.git.GitRepository.delete_branch}
156
157     >>> import gbp.git, shutil
158     >>> repo = gbp.git.GitRepository(repo_dir)
159     >>> repo.create_branch("bar")
160     >>> repo.delete_branch("bar")
161     >>> repo.delete_branch("master")
162     Traceback (most recent call last):
163     ...
164     GitRepositoryError: Can't delete the branch you're on
165     """
166
167 def test_set_branch():
168     """
169     Switch to branch named I{foo}
170
171     Methods tested:
172          - L{gbp.git.GitRepository.set_branch}
173          - L{gbp.git.GitRepository.get_branch}
174          - L{gbp.git.GitRepository.branch}
175
176     >>> import gbp.git
177     >>> repo = gbp.git.GitRepository(repo_dir)
178     >>> repo.set_branch("foo")
179     >>> repo.get_branch() == "foo"
180     True
181     >>> repo.branch == "foo"
182     True
183     """
184
185
186 def test_rename_branch():
187     """
188     Create branch named I{baz}, rename it to I{bax} and finally delete it
189
190     Methods tested:
191          - L{gbp.git.GitRepository.create_branch}
192          - L{gbp.git.GitRepository.rename_branch}
193          - L{gbp.git.GitRepository.delete_branch}
194
195     >>> import gbp.git
196     >>> repo = gbp.git.GitRepository(repo_dir)
197     >>> repo.create_branch("baz")
198     >>> repo.rename_branch("baz", "bax")
199     >>> repo.delete_branch("bax")
200     """
201
202
203 def test_set_upstream_branch():
204     """
205     Set upstream branch master -> origin/master
206
207     >>> import os, shutil
208     >>> import gbp.git
209     >>> repo = gbp.git.GitRepository(repo_dir)
210     >>> os.makedirs(os.path.join(repo.git_dir, 'refs/remotes/origin'))
211     >>> shutil.copy(os.path.join(repo.git_dir, 'refs/heads/master'), \
212                     os.path.join(repo.git_dir, 'refs/remotes/origin/'))
213     >>> repo.add_remote_repo('origin', 'git://git.example.com/git/origin')
214     >>> repo.set_upstream_branch('master', 'origin/master')
215     >>> repo.get_upstream_branch('master')
216     'origin/master'
217     >>> repo.set_upstream_branch('bla', 'origin/master')
218     Traceback (most recent call last):
219     GitRepositoryError: Branch bla doesn't exist!
220     >>> repo.set_upstream_branch('foo', 'origin/bla')
221     Traceback (most recent call last):
222     GitRepositoryError: Branch origin/bla doesn't exist!
223     """
224
225 def test_get_upstream_branch():
226     """
227     Get info about upstream branches set in test_set_upstream_branch
228
229     >>> import gbp.git
230     >>> repo = gbp.git.GitRepository(repo_dir)
231     >>> repo.get_upstream_branch('master')
232     'origin/master'
233     >>> repo.get_upstream_branch('foo')
234     ''
235     >>> repo.get_upstream_branch('bla')
236     Traceback (most recent call last):
237     GitRepositoryError: Branch bla doesn't exist!
238     """
239
240 def test_tag():
241     """
242     Create a tag named I{tag} and check it's existance
243
244     Methods tested:
245          - L{gbp.git.GitRepository.create_tag}
246          - L{gbp.git.GitRepository.verify_tag}
247          - L{gbp.git.GitRepository.has_tag}
248          - L{gbp.git.GitRepository.get_tags}
249
250     >>> import gbp.git
251     >>> repo = gbp.git.GitRepository(repo_dir)
252     >>> repo.create_tag("tag")
253     >>> repo.has_tag("tag")
254     True
255     >>> repo.has_tag("unknown")
256     False
257     >>> repo.create_tag("tag2", msg="foo")
258     >>> repo.has_tag("tag2")
259     True
260     >>> repo.verify_tag("tag2")
261     False
262     >>> repo.get_tags()
263     ['tag', 'tag2']
264     >>> repo.tags
265     ['tag', 'tag2']
266     """
267
268 def test_describe():
269     """
270     Describe commit-ish
271
272     Methods tested:
273          - L{gbp.git.GitRepository.describe}
274
275     >>> import gbp.git
276     >>> repo = gbp.git.GitRepository(repo_dir)
277     >>> sha = repo.rev_parse('HEAD')
278     >>> repo.describe('HEAD')
279     'tag2'
280     >>> repo.describe('HEAD', longfmt=True) == 'tag2-0-g%s' % sha[:7]
281     True
282     >>> repo.describe('HEAD', pattern='foo*')
283     Traceback (most recent call last):
284     ...
285     GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
286     >>> repo.describe('HEAD', pattern='foo*', always=True) == sha[:7]
287     True
288     >>> repo.describe('HEAD', always=True, abbrev=16)
289     'tag2'
290     >>> repo.describe('HEAD', pattern='foo*', always=True, abbrev=16) == sha[:16]
291     True
292     >>> tag = repo.describe('HEAD', longfmt=True, abbrev=16) == 'tag2-0-g%s' % sha[:16]
293     >>> repo.delete_tag('tag2')
294     >>> repo.describe('HEAD', tags=True)
295     'tag'
296     >>> repo.describe('HEAD', tags=True, exact_match=True)
297     'tag'
298     >>> repo.create_tag('tag2', msg='foo')
299     """
300
301 def test_find_tag():
302     """
303     Find tags
304
305     Methods tested:
306          - L{gbp.git.GitRepository.find_tag}
307
308     >>> import gbp.git
309     >>> repo = gbp.git.GitRepository(repo_dir)
310     >>> repo.find_tag('HEAD')
311     'tag2'
312     >>> repo.find_tag('HEAD', pattern='foo*')
313     Traceback (most recent call last):
314     ...
315     GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
316     """
317
318 def test_move_tag():
319     """
320     Move a tag
321
322     Methods tested:
323          - L{gbp.git.GitRepository.move_tag}
324          - L{gbp.git.GitRepository.has_tag}
325
326     >>> import gbp.git
327     >>> repo = gbp.git.GitRepository(repo_dir)
328     >>> repo.move_tag("tag", "moved")
329     >>> repo.has_tag("tag")
330     False
331     >>> repo.has_tag("moved")
332     True
333     """
334
335 def test_delete_tag():
336     """
337     Delete tags
338
339     Methods tested:
340          - L{gbp.git.GitRepository.delete_tag}
341          - L{gbp.git.GitRepository.has_tag}
342
343     >>> import gbp.git
344     >>> repo = gbp.git.GitRepository(repo_dir)
345     >>> repo.has_tag("moved")
346     True
347     >>> repo.delete_tag("moved")
348     >>> repo.has_tag("moved")
349     False
350     """
351
352 def test_get_obj_type():
353     """
354     Find commit SHA1 related to tags
355
356     Methods tested:
357          - L{gbp.git.GitRepository.create_tag}
358          - L{gbp.git.GitRepository.get_obj_type}
359          - L{gbp.git.GitRepository.delete_tag}
360
361     >>> import gbp.git
362     >>> repo = gbp.git.GitRepository(repo_dir)
363     >>> repo.create_tag("tag3", "tag msg")
364     >>> repo.get_obj_type("tag3")
365     'tag'
366     >>> repo.get_obj_type("HEAD")
367     'commit'
368     >>> repo.get_obj_type("HEAD:testfile")
369     'blob'
370     >>> repo.delete_tag("tag3")
371     """
372
373 def test_list_files():
374     """
375     List files in the index
376
377     Methods tested:
378          - L{gbp.git.GitRepository.list_files}
379          - L{gbp.git.GitRepository.add_files}
380          - L{gbp.git.GitRepository.commit_staged}
381          - L{gbp.git.GitRepository.commit_files}
382          - L{gbp.git.GitRepository.force_head}
383
384     >>> import gbp.git, os, shutil
385     >>> repo = gbp.git.GitRepository(repo_dir)
386     >>> src = os.path.join(repo.path, ".git/HEAD")
387     >>> dst = os.path.join(repo.path, "testfile")
388     >>> repo.list_files()
389     ['testfile']
390     >>> repo.list_files(['modified'])
391     []
392     >>> repo.list_files(['modified', 'deleted'])
393     []
394     >>> repo.list_files(['modified', 'deleted', 'cached'])
395     ['testfile']
396     >>> shutil.copy(src, dst)
397     >>> repo.list_files(['modified'])
398     ['testfile']
399     >>> repo.add_files(dst)
400     >>> repo.commit_staged(msg="foo")
401     >>> repo.list_files(['modified'])
402     []
403     >>> repo.list_files(['foo'])
404     Traceback (most recent call last):
405     ...
406     GitRepositoryError: Unknown type 'foo'
407     >>> repo.force_head('HEAD^', hard=True)
408     >>> repo.list_files(['modified'])
409     []
410     >>> shutil.copy(src, dst)
411     >>> repo.list_files(['modified'])
412     ['testfile']
413     >>> repo.commit_files(dst, msg="foo")
414     >>> repo.list_files(['modified'])
415     []
416     """
417
418 def test_get_commits():
419     """
420     Test listing commits
421
422     Methods tested:
423          - L{gbp.git.GitRepository.get_commits}
424
425     >>> import gbp.git
426     >>> repo = gbp.git.GitRepository(repo_dir)
427     >>> commits = repo.get_commits()
428     >>> type(commits) == list and len(commits) == 2
429     True
430     >>> len(repo.get_commits(num=1)) == 1
431     True
432     >>> commits2 = repo.get_commits(since='HEAD~1')
433     >>> len(commits2) == 1
434     True
435     >>> commits2[0] == commits[0]
436     True
437     >>> commits2 = repo.get_commits(until='HEAD~1')
438     >>> len(commits2) == 1
439     True
440     >>> commits2[0] == commits[-1]
441     True
442     >>> repo.get_commits(paths=['foo', 'bar'])
443     []
444     >>> repo.get_commits(paths=['testfile']) == commits
445     True
446     """
447
448
449 def test_get_commit_info():
450     """
451     Test inspecting commits
452
453     Methods tested:
454          - L{gbp.git.GitRepository.get_commit_info}
455
456     >>> import gbp.git
457     >>> from datetime import datetime
458     >>> repo = gbp.git.GitRepository(repo_dir)
459     >>> info = repo.get_commit_info('HEAD')
460     >>> info['id']
461     'HEAD'
462     >>> info['body']
463     ''
464     >>> info['subject']
465     'foo'
466     >>> '@' in info['author'].email
467     True
468     >>> '@' in info['committer'].email
469     True
470     >>> now = datetime.now()
471     >>> (now - datetime.fromtimestamp(int(info['author'].date.split()[0]))).seconds < 10
472     True
473     >>> (now - datetime.fromtimestamp(int(info['committer'].date.split()[0]))).seconds < 10
474     True
475     >>> info['patchname']
476     'foo'
477     >>> info['files']
478     defaultdict(<type 'list'>, {'M': ['testfile']})
479     >>> repo.get_subject('HEAD')
480     'foo'
481     """
482
483 def test_diff():
484     """
485     Test git-diff
486
487     Methods tested:
488          - L{gbp.git.GitRepository.diff}
489
490     >>> import gbp.git
491     >>> repo = gbp.git.GitRepository(repo_dir)
492     >>> len(repo.diff('HEAD~1', 'HEAD')) > 3
493     True
494     >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile')) > 3
495     True
496     >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile', text=True)) > 3
497     True
498     >>> len(repo.diff('HEAD~1', 'HEAD', 'filenotexist')) == 0
499     True
500     """
501
502 def test_diff_status():
503     """
504     Methods tested:
505         - L{gbp.git.GitRepository.diff_status}
506
507     >>> import gbp.git
508     >>> repo = gbp.git.GitRepository(repo_dir)
509     >>> repo.diff_status("HEAD", "HEAD")
510     defaultdict(<type 'list'>, {})
511     >>> repo.diff_status("HEAD~1", "HEAD")
512     defaultdict(<type 'list'>, {'M': ['testfile']})
513     """
514
515 def test_mirror_clone():
516     """
517     Mirror a repository
518
519     Methods tested:
520          - L{gbp.git.GitRepository.clone}
521          - L{gbp.git.GitRepository.is_empty}
522          - L{gbp.git.GitRepository.set_branch}
523          - L{gbp.git.GitRepository.has_branch}
524          - L{gbp.git.GitRepository.branch}
525
526     >>> import gbp.git
527     >>> repo = gbp.git.GitRepository(repo_dir)
528     >>> repo.set_branch('master')
529     >>> mirror = gbp.git.GitRepository.clone(mirror_clone_dir, repo.path, mirror=True)
530     >>> mirror.is_empty()
531     False
532     >>> mirror.branch
533     'master'
534     >>> mirror.has_branch('foo')
535     True
536     >>> mirror.has_branch('bar')
537     False
538     >>> mirror.set_branch('foo')
539     >>> mirror.branch
540     'foo'
541     >>> mirror.force_head('foo^')
542     """
543
544 def test_clone():
545     """
546     Clone a repository
547
548     Methods tested:
549          - L{gbp.git.GitRepository.clone}
550          - L{gbp.git.GitRepository.is_empty}
551          - L{gbp.git.GitRepository.set_branch}
552          - L{gbp.git.GitRepository.branch}
553          - L{gbp.git.GitRepository.get_merge_branch}
554          - L{gbp.git.GitRepository.get_remote_branches}
555          - L{gbp.git.GitRepository.get_local_branches}
556          - L{gbp.git.GitRepository.get_remote_repos}
557          - L{gbp.git.GitRepository.has_remote_repo}
558
559     >>> import gbp.git
560     >>> repo = gbp.git.GitRepository(repo_dir)
561     >>> repo.set_branch('master')
562     >>> clone = gbp.git.GitRepository.clone(clone_dir, repo.path)
563     >>> clone.is_empty()
564     False
565     >>> clone.branch
566     'master'
567     >>> clone.get_remote_branches()
568     ['origin/HEAD', 'origin/foo', 'origin/master']
569     >>> clone.get_local_branches()
570     ['master']
571     >>> clone.get_merge_branch('master')
572     'origin/master'
573     >>> clone.create_branch('foo', 'origin/foo')
574     >>> clone.get_merge_branch('foo')
575     'origin/foo'
576     >>> clone.create_branch('bar')
577     >>> clone.get_merge_branch('bar') # None if no merge branch exists
578     >>> clone.get_local_branches()
579     ['bar', 'foo', 'master']
580     >>> remotes = clone.get_remote_repos()
581     >>> {'origin': [repo_dir, repo_dir]} == remotes
582     True
583     >>> clone.has_remote_repo('origin')
584     True
585     >>> clone.has_branch('origin/master', remote=True)
586     True
587     >>> clone.has_remote_repo('godiug')
588     False
589     """
590
591 def test_get_remotes():
592     """
593     Merge a branch
594
595     Methods tested:
596          - L{gbp.git.GitRepository.get_remotes}
597
598     >>> import os
599     >>> import gbp.git.repository
600     >>> repo = gbp.git.repository.GitRepository(os.path.join(clone_dir, 'repo'))
601     >>> remotes = repo.get_remotes()
602     >>> len(remotes)
603     1
604     >>> origin = remotes['origin']
605     >>> origin.name
606     'origin'
607     >>> origin.fetch_url == repo_dir
608     True
609     >>> origin.push_urls == [repo_dir]
610     True
611     """
612
613 def test_merge():
614     """
615     Merge a branch
616
617     Methods tested:
618          - L{gbp.git.GitRepository.merge}
619          - L{gbp.git.GitRepository.set_branch}
620
621     >>> import gbp.git
622     >>> repo = gbp.git.GitRepository(repo_dir)
623     >>> repo.set_branch('master')
624     >>> repo.merge('foo')
625     """
626
627 def test_pull():
628     """
629     Pull from a remote repository
630
631     Methods tested:
632          - L{gbp.git.GitRepository.set_branch}
633          - L{gbp.git.GitRepository.pull}
634
635     >>> import gbp.git, os
636     >>> d = os.path.join(clone_dir, 'repo')
637     >>> clone = gbp.git.GitRepository(d)
638     >>> clone.set_branch('master')
639     >>> clone.pull()
640     >>> clone.pull(all_remotes=True)
641     >>> clone.pull('origin', all_remotes=True)
642     """
643
644 def test_fetch():
645     """
646     Fetch from a remote repository
647
648     Methods tested:
649          - L{gbp.git.GitRepository.fetch}
650          - L{gbp.git.GitRepository.push}
651          - L{gbp.git.GitRepository.push_tag}
652          - L{gbp.git.GitRepository.add_remote_repo}
653          - L{gbp.git.GitRepository.remove_remote_repo}
654
655     >>> import gbp.git, os
656     >>> d = os.path.join(clone_dir, 'repo')
657     >>> clone = gbp.git.GitRepository(d)
658     >>> clone.fetch()
659     >>> clone.push()
660     >>> clone.push('origin')
661     >>> clone.push('origin', 'master')
662     >>> clone.push('origin', 'master', force=True)
663     >>> clone.create_tag('tag3')
664     >>> clone.push_tag('origin', 'tag3')
665     >>> clone.create_tag('tag4')
666     >>> clone.push('origin', 'master', tags=True)
667     >>> clone.add_remote_repo('foo', repo_dir)
668     >>> clone.fetch('foo')
669     >>> clone.fetch('foo', tags=True)
670     >>> clone.fetch('foo', refspec='refs/heads/master')
671     >>> clone.fetch(all_remotes=True)
672     >>> clone.remove_remote_repo('foo')
673     """
674
675 def test_create_bare():
676     """
677     Create a bare repository
678
679     Methods tested:
680          - L{gbp.git.GitRepository.create}
681          - L{gbp.git.GitRepository.is_empty}
682
683     >>> import gbp.git
684     >>> bare = gbp.git.GitRepository.create(bare_dir, bare=True, description="msg")
685     >>> bare.path == bare_dir
686     True
687     >>> bare.git_dir == bare_dir
688     True
689     >>> type(bare) == gbp.git.GitRepository
690     True
691     >>> bare.is_empty()
692     True
693     >>> bare.is_clean()
694     (True, '')
695     """
696
697 def test_nonexistant():
698     """
699     Check that accessing a non existant repository fails.
700
701     Methods tested:
702          - L{gbp.git.GitRepository.__init__}
703
704     >>> import gbp.git
705     >>> bare = gbp.git.GitRepository("/does/not/exist")
706     Traceback (most recent call last):
707     ...
708     GitRepositoryError: No Git repository at '/does/not/exist' (or any parent dir)
709     """
710
711 def test_create_noperm():
712     """
713     Check that creating a repository at a path that isn't writeable fails
714
715     Methods tested:
716          - L{gbp.git.GitRepository.create}
717
718     >>> import gbp.git
719     >>> gbp.git.GitRepository.create("/does/not/exist")
720     Traceback (most recent call last):
721     ...
722     GitRepositoryError: Cannot create Git repository at '/does/not/exist': Permission denied
723     """
724
725 def test_checkout():
726     """
727     Checkout treeishs
728
729     Methods tested:
730          - L{gbp.git.GitRepository.checkout}
731          - L{gbp.git.GitRepository.get_branch}
732          - L{gbp.git.GitRepository.set_branch}
733          - L{gbp.git.GitRepository.rev_parse}
734
735     Properties tested:
736          - L{gbp.git.GitRepository.branch}
737          - L{gbp.git.GitRepository.tags}
738
739     >>> import gbp.git
740     >>> repo = gbp.git.GitRepository(repo_dir)
741     >>> repo.checkout('master')
742     >>> repo.branch
743     'master'
744     >>> repo.rev_parse('doesnotexist')
745     Traceback (most recent call last):
746     ...
747     GitRepositoryError: revision 'doesnotexist' not found
748     >>> sha1 = repo.rev_parse('master', short=10)
749     >>> len(sha1)
750     10
751     >>> sha1 = repo.rev_parse('master')
752     >>> len(sha1)
753     40
754     >>> repo.checkout(sha1)
755     >>> repo.branch
756     >>> repo.get_branch()
757     Traceback (most recent call last):
758     ...
759     GitRepositoryError: Currently not on a branch
760     >>> tag = repo.tags[0]
761     >>> repo.checkout(tag)
762     >>> repo.branch
763     """
764
765 def test_gc():
766     """
767     Test garbace collection
768
769     Methods tested:
770          - L{gbp.git.GitRepository.collect_garbage}
771
772     >>> import gbp.git
773     >>> repo = gbp.git.GitRepository(repo_dir)
774     >>> repo.collect_garbage()
775     """
776
777 def test_grep_log():
778     """
779     Test grepping through commit messages
780
781     Methods tested:
782         - L{gbp.git.GitRepository.grep_log}
783
784     >>> import gbp.git
785     >>> repo = gbp.git.GitRepository(repo_dir)
786     >>> repo.set_branch('master')
787     >>> len(repo.grep_log('foo')) == 2
788     True
789     >>> len(repo.grep_log('foo', 'master')) == 2
790     True
791     >>> repo.grep_log('blafasel')
792     []
793     >>> repo.grep_log('foo', 'doesnotexist')
794     Traceback (most recent call last):
795     ...
796     GitRepositoryError: Error grepping log for foo: fatal: bad revision 'doesnotexist'
797     """
798
799 def test_is_ff():
800     """
801     Test if branch is fast forwardable
802
803     Methods tested:
804         - L{gbp.git.GitRepository.is_fast_forward}
805
806     >>> import gbp.git
807     >>> repo = gbp.git.GitRepository(repo_dir)
808     >>> repo.is_fast_forward('master', 'foo')
809     (True, True)
810     >>> repo.create_branch('ff', 'HEAD^')
811     >>> repo.is_fast_forward('ff', 'master')
812     (True, False)
813     >>> repo.is_fast_forward('master', 'ff')
814     (False, True)
815     """
816
817 def test_update_ref():
818     """
819     Test updating a reference
820
821     Methods tested:
822         - L{gbp.git.GitRepository.update_ref}
823
824     >>> import gbp.git, os
825     >>> repo = gbp.git.GitRepository(repo_dir)
826     >>> repo.update_ref('new_ref', 'master', msg='update')
827     >>> os.path.exists(os.path.join(repo.git_dir, 'new_ref'))
828     True
829     """
830
831
832 def test_make_tree():
833     """
834     Test git-mk-tree
835
836     Methods tested:
837         - L{gbp.git.GitRepository.write_file}
838         - L{gbp.git.GitRepository.list_tree}
839         - L{gbp.git.GitRepository.make_tree}
840
841     >>> import gbp.git
842     >>> repo = gbp.git.GitRepository(repo_dir)
843     >>> sha1 = repo.write_file('testfile')
844     >>> sha1
845     '19af7398c894bc5e86e17259317e4db519e9241f'
846     >>> head = repo.list_tree('HEAD')
847     >>> head
848     [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
849     >>> head.append(['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile2'])
850     >>> newtree = repo.make_tree(head)
851     >>> newtree
852     '745951810c9e22fcc6de9b23f05efd6ab5512123'
853     >>> repo.list_tree(newtree, recurse=False, paths='testfile')
854     [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
855     """
856
857
858 def test_update_submodules():
859     """
860     Updating submodules if we don't have any is a noop
861
862     Methods tested:
863         - L{gbp.git.GitRepository.has_submodules}
864         - L{gbp.git.GitRepository.update_submodules}
865
866     >>> import gbp.git
867     >>> repo = gbp.git.GitRepository(repo_dir)
868     >>> repo.has_submodules()
869     False
870     >>> repo.update_submodules()
871     """
872
873 def test_get_merge_base():
874     """
875     Find the common ancestor of two objects
876
877     Methods tested:
878         - L{gbp.git.GitRepository.get_merge_base}
879
880     >>> import gbp.git
881     >>> repo = gbp.git.GitRepository(repo_dir)
882     >>> sha1 = repo.get_merge_base('master', 'foo')
883     >>> len(sha1)
884     40
885     >>> repo.get_merge_base('master', 'doesnotexist')
886     Traceback (most recent call last):
887     ...
888     GitRepositoryError: Failed to get common ancestor: fatal: Not a valid object name doesnotexist
889     """
890
891 def test_status():
892     r"""
893     Methods tested:
894         - L{gbp.git.GitRepository.status}
895
896     >>> import gbp.git, os, shutil
897     >>> repo = gbp.git.GitRepository(repo_dir)
898     >>> fname = os.path.join(repo.path, "test_status")
899     >>> shutil.copy(os.path.join(repo.path, ".git/HEAD"), fname)
900     >>> list(repo.status().items())
901     [('??', ['test_status'])]
902     >>> list(repo.status().items())
903     []
904     >>> list(repo.status().items())
905     [('??', ['test_status'])]
906     >>> repo.add_files(repo.path, force=True)
907     >>> repo.commit_all(msg='added %s' % fname)
908     >>> _ = repo._git_inout('mv', [fname, fname + 'new'])
909     >>> list(repo.status().items())
910     [('R ', ['test_status\x00test_statusnew'])]
911     """
912
913 def test_cmd_has_feature():
914     r"""
915     Methods tested:
916         - L{gbp.git.GitRepository._cmd_has_feature}
917
918     >>> import gbp.git
919     >>> repo = gbp.git.GitRepository(repo_dir)
920     >>> repo._cmd_has_feature("commit", "a")
921     True
922     >>> repo._cmd_has_feature("commit", "reuse-message")
923     True
924     >>> repo._cmd_has_feature("merge", "n")
925     True
926     >>> repo._cmd_has_feature("merge", "stat")
927     True
928     >>> repo._cmd_has_feature("format-patch", "cc")
929     True
930     >>> repo._cmd_has_feature("merge", "foobaroption")
931     False
932     >>> repo._cmd_has_feature("foobarcmd", "foobaroption")
933     Traceback (most recent call last):
934     ...
935     GitRepositoryError: Invalid git command 'foobarcmd': No manual entry for gitfoobarcmd
936     >>> repo._cmd_has_feature("show", "standard-notes")
937     True
938     >>> repo._cmd_has_feature("show", "no-standard-notes")
939     True
940     """
941
942 def test_teardown():
943     """
944     Perform the teardown
945
946     >>> context.teardown()
947     """
948
949 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: