GitRepository: Add clean() method
[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 = 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
72     Properties tested:
73          - L{gbp.git.GitRepository.head}
74
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]
80     False
81     >>> repo.is_clean(ignore_untracked=True)[0]
82     True
83     >>> repo.add_files(repo.path, force=True)
84     >>> repo.commit_all(msg="foo")
85     >>> repo.is_clean()[0]
86     True
87     >>> h = repo.head
88     >>> len(h)
89     40
90     """
91
92
93 def test_branch_master():
94     """
95     First branch is called I{master}
96
97     Methods tested:
98          - L{gbp.git.GitRepository.get_branch}
99     >>> import gbp.git, shutil
100     >>> repo = gbp.git.GitRepository(repo_dir)
101     >>> repo.get_branch()
102     'master'
103     >>> repo.branch
104     'master'
105     """
106
107 def test_clean():
108     """
109     Remove untracked files from the working tree
110
111     Methods tested:
112          - L{gbp.git.GitRepository.clean}
113
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]
120     False
121     >>> repo.clean(directories=True, force=True)
122     >>> repo.is_clean()[0]
123     True
124     """
125
126 def test_create_branch():
127     """
128     Create a branch name I{foo}
129
130     Methods tested:
131          - L{gbp.git.GitRepository.create_branch}
132          - L{gbp.git.GitRepository.branch_contains}
133
134     >>> import gbp.git, shutil
135     >>> repo = gbp.git.GitRepository(repo_dir)
136     >>> repo.create_branch("foo")
137     >>> repo.branch_contains("foo", 'HEAD')
138     True
139     >>> repo.branch_contains("doesnotexist", 'HEAD', remote=True)
140     False
141     """
142
143 def test_delete_branch():
144     """
145     Create a branch named I{foo2} and delete it
146
147     Methods tested:
148          - L{gbp.git.GitRepository.create_branch}
149          - L{gbp.git.GitRepository.delete_branch}
150
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):
157     ...
158     GitRepositoryError: Can't delete the branch you're on
159     """
160
161 def test_set_branch():
162     """
163     Switch to branch named I{foo}
164
165     Methods tested:
166          - L{gbp.git.GitRepository.set_branch}
167          - L{gbp.git.GitRepository.get_branch}
168          - L{gbp.git.GitRepository.branch}
169
170     >>> import gbp.git
171     >>> repo = gbp.git.GitRepository(repo_dir)
172     >>> repo.set_branch("foo")
173     >>> repo.get_branch() == "foo"
174     True
175     >>> repo.branch == "foo"
176     True
177     """
178
179
180 def test_rename_branch():
181     """
182     Create branch named I{baz}, rename it to I{bax} and finally delete it
183
184     Methods tested:
185          - L{gbp.git.GitRepository.create_branch}
186          - L{gbp.git.GitRepository.rename_branch}
187          - L{gbp.git.GitRepository.delete_branch}
188
189     >>> import gbp.git
190     >>> repo = gbp.git.GitRepository(repo_dir)
191     >>> repo.create_branch("baz")
192     >>> repo.rename_branch("baz", "bax")
193     >>> repo.delete_branch("bax")
194     """
195
196
197 def test_set_upstream_branch():
198     """
199     Set upstream branch master -> origin/master
200
201     >>> import os, shutil
202     >>> import gbp.git
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')
210     'origin/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!
217     """
218
219 def test_get_upstream_branch():
220     """
221     Get info about upstream branches set in test_set_upstream_branch
222
223     >>> import gbp.git
224     >>> repo = gbp.git.GitRepository(repo_dir)
225     >>> repo.get_upstream_branch('master')
226     'origin/master'
227     >>> repo.get_upstream_branch('foo')
228     ''
229     >>> repo.get_upstream_branch('bla')
230     Traceback (most recent call last):
231     GitRepositoryError: Branch bla doesn't exist!
232     """
233
234 def test_tag():
235     """
236     Create a tag named I{tag} and check it's existance
237
238     Methods tested:
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}
243
244     >>> import gbp.git
245     >>> repo = gbp.git.GitRepository(repo_dir)
246     >>> repo.create_tag("tag")
247     >>> repo.has_tag("tag")
248     True
249     >>> repo.has_tag("unknown")
250     False
251     >>> repo.create_tag("tag2", msg="foo")
252     >>> repo.has_tag("tag2")
253     True
254     >>> repo.verify_tag("tag2")
255     False
256     >>> repo.get_tags()
257     ['tag', 'tag2']
258     >>> repo.tags
259     ['tag', 'tag2']
260     """
261
262 def test_describe():
263     """
264     Describe commit-ish
265
266     Methods tested:
267          - L{gbp.git.GitRepository.describe}
268
269     >>> import gbp.git
270     >>> repo = gbp.git.GitRepository(repo_dir)
271     >>> sha = repo.rev_parse('HEAD')
272     >>> repo.describe('HEAD')
273     'tag2'
274     >>> repo.describe('HEAD', longfmt=True) == 'tag2-0-g%s' % sha[:7]
275     True
276     >>> repo.describe('HEAD', pattern='foo*')
277     Traceback (most recent call last):
278     ...
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]
281     True
282     >>> repo.describe('HEAD', always=True, abbrev=16)
283     'tag2'
284     >>> repo.describe('HEAD', pattern='foo*', always=True, abbrev=16) == sha[:16]
285     True
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)
289     'tag'
290     >>> repo.describe('HEAD', tags=True, exact_match=True)
291     'tag'
292     >>> repo.create_tag('tag2', msg='foo')
293     """
294
295 def test_find_tag():
296     """
297     Find tags
298
299     Methods tested:
300          - L{gbp.git.GitRepository.find_tag}
301
302     >>> import gbp.git
303     >>> repo = gbp.git.GitRepository(repo_dir)
304     >>> repo.find_tag('HEAD')
305     'tag2'
306     >>> repo.find_tag('HEAD', pattern='foo*')
307     Traceback (most recent call last):
308     ...
309     GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
310     """
311
312 def test_move_tag():
313     """
314     Move a tag
315
316     Methods tested:
317          - L{gbp.git.GitRepository.move_tag}
318          - L{gbp.git.GitRepository.has_tag}
319
320     >>> import gbp.git
321     >>> repo = gbp.git.GitRepository(repo_dir)
322     >>> repo.move_tag("tag", "moved")
323     >>> repo.has_tag("tag")
324     False
325     >>> repo.has_tag("moved")
326     True
327     """
328
329 def test_delete_tag():
330     """
331     Delete tags
332
333     Methods tested:
334          - L{gbp.git.GitRepository.delete_tag}
335          - L{gbp.git.GitRepository.has_tag}
336
337     >>> import gbp.git
338     >>> repo = gbp.git.GitRepository(repo_dir)
339     >>> repo.has_tag("moved")
340     True
341     >>> repo.delete_tag("moved")
342     >>> repo.has_tag("moved")
343     False
344     """
345
346 def test_get_obj_type():
347     """
348     Find commit SHA1 related to tags
349
350     Methods tested:
351          - L{gbp.git.GitRepository.create_tag}
352          - L{gbp.git.GitRepository.get_obj_type}
353          - L{gbp.git.GitRepository.delete_tag}
354
355     >>> import gbp.git
356     >>> repo = gbp.git.GitRepository(repo_dir)
357     >>> repo.create_tag("tag3", "tag msg")
358     >>> repo.get_obj_type("tag3")
359     'tag'
360     >>> repo.get_obj_type("HEAD")
361     'commit'
362     >>> repo.get_obj_type("HEAD:testfile")
363     'blob'
364     >>> repo.delete_tag("tag3")
365     """
366
367 def test_list_files():
368     """
369     List files in the index
370
371     Methods tested:
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}
377
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()
383     ['testfile']
384     >>> repo.list_files(['modified'])
385     []
386     >>> repo.list_files(['modified', 'deleted'])
387     []
388     >>> repo.list_files(['modified', 'deleted', 'cached'])
389     ['testfile']
390     >>> shutil.copy(src, dst)
391     >>> repo.list_files(['modified'])
392     ['testfile']
393     >>> repo.add_files(dst)
394     >>> repo.commit_staged(msg="foo")
395     >>> repo.list_files(['modified'])
396     []
397     >>> repo.list_files(['foo'])
398     Traceback (most recent call last):
399     ...
400     GitRepositoryError: Unknown type 'foo'
401     >>> repo.force_head('HEAD^', hard=True)
402     >>> repo.list_files(['modified'])
403     []
404     >>> shutil.copy(src, dst)
405     >>> repo.list_files(['modified'])
406     ['testfile']
407     >>> repo.commit_files(dst, msg="foo")
408     >>> repo.list_files(['modified'])
409     []
410     """
411
412 def test_get_commits():
413     """
414     Test listing commits
415
416     Methods tested:
417          - L{gbp.git.GitRepository.get_commits}
418
419     >>> import gbp.git
420     >>> repo = gbp.git.GitRepository(repo_dir)
421     >>> commits = repo.get_commits()
422     >>> type(commits) == list and len(commits) == 2
423     True
424     >>> len(repo.get_commits(num=1)) == 1
425     True
426     >>> commits2 = repo.get_commits(since='HEAD~1')
427     >>> len(commits2) == 1
428     True
429     >>> commits2[0] == commits[0]
430     True
431     >>> commits2 = repo.get_commits(until='HEAD~1')
432     >>> len(commits2) == 1
433     True
434     >>> commits2[0] == commits[-1]
435     True
436     >>> repo.get_commits(paths=['foo', 'bar'])
437     []
438     >>> repo.get_commits(paths=['testfile']) == commits
439     True
440     """
441
442
443 def test_get_commit_info():
444     """
445     Test inspecting commits
446
447     Methods tested:
448          - L{gbp.git.GitRepository.get_commit_info}
449
450     >>> import gbp.git
451     >>> from datetime import datetime
452     >>> repo = gbp.git.GitRepository(repo_dir)
453     >>> info = repo.get_commit_info('HEAD')
454     >>> info['id']
455     'HEAD'
456     >>> info['body']
457     ''
458     >>> info['subject']
459     'foo'
460     >>> '@' in info['author'].email
461     True
462     >>> '@' in info['committer'].email
463     True
464     >>> now = datetime.now()
465     >>> (now - datetime.fromtimestamp(int(info['author'].date.split()[0]))).seconds < 10
466     True
467     >>> (now - datetime.fromtimestamp(int(info['committer'].date.split()[0]))).seconds < 10
468     True
469     >>> info['patchname']
470     'foo'
471     >>> info['files']
472     defaultdict(<type 'list'>, {'M': ['testfile']})
473     >>> repo.get_subject('HEAD')
474     'foo'
475     """
476
477 def test_diff():
478     """
479     Test git-diff
480
481     Methods tested:
482          - L{gbp.git.GitRepository.diff}
483
484     >>> import gbp.git
485     >>> repo = gbp.git.GitRepository(repo_dir)
486     >>> len(repo.diff('HEAD~1', 'HEAD')) > 3
487     True
488     >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile')) > 3
489     True
490     >>> len(repo.diff('HEAD~1', 'HEAD', 'filenotexist')) == 0
491     True
492     """
493
494 def test_mirror_clone():
495     """
496     Mirror a repository
497
498     Methods tested:
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}
504
505     >>> import gbp.git
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()
510     False
511     >>> mirror.branch
512     'master'
513     >>> mirror.has_branch('foo')
514     True
515     >>> mirror.has_branch('bar')
516     False
517     >>> mirror.set_branch('foo')
518     >>> mirror.branch
519     'foo'
520     >>> mirror.force_head('foo^')
521     """
522
523 def test_clone():
524     """
525     Clone a repository
526
527     Methods tested:
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}
537
538     >>> import gbp.git
539     >>> repo = gbp.git.GitRepository(repo_dir)
540     >>> repo.set_branch('master')
541     >>> clone = gbp.git.GitRepository.clone(clone_dir, repo.path)
542     >>> clone.is_empty()
543     False
544     >>> clone.branch
545     'master'
546     >>> clone.get_remote_branches()
547     ['origin/HEAD', 'origin/foo', 'origin/master']
548     >>> clone.get_local_branches()
549     ['master']
550     >>> clone.get_merge_branch('master')
551     'origin/master'
552     >>> clone.create_branch('foo', 'origin/foo')
553     >>> clone.get_merge_branch('foo')
554     'origin/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()
560     ['origin']
561     >>> clone.has_remote_repo('origin')
562     True
563     >>> clone.has_branch('origin/master', remote=True)
564     True
565     >>> clone.has_remote_repo('godiug')
566     False
567     """
568
569 def test_merge():
570     """
571     Merge a branch
572
573     Methods tested:
574          - L{gbp.git.GitRepository.merge}
575          - L{gbp.git.GitRepository.set_branch}
576
577     >>> import gbp.git
578     >>> repo = gbp.git.GitRepository(repo_dir)
579     >>> repo.set_branch('master')
580     >>> repo.merge('foo')
581     """
582
583 def test_pull():
584     """
585     Pull from a remote repository
586
587     Methods tested:
588          - L{gbp.git.GitRepository.set_branch}
589          - L{gbp.git.GitRepository.pull}
590
591     >>> import gbp.git, os
592     >>> d = os.path.join(clone_dir, 'repo')
593     >>> clone = gbp.git.GitRepository(d)
594     >>> clone.set_branch('master')
595     >>> clone.pull()
596     """
597
598 def test_fetch():
599     """
600     Fetch from a remote repository
601
602     Methods tested:
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}
608
609     >>> import gbp.git, os
610     >>> d = os.path.join(clone_dir, 'repo')
611     >>> clone = gbp.git.GitRepository(d)
612     >>> clone.fetch()
613     >>> clone.push()
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')
624     """
625
626 def test_create_bare():
627     """
628     Create a bare repository
629
630     Methods tested:
631          - L{gbp.git.GitRepository.create}
632          - L{gbp.git.GitRepository.is_empty}
633
634     >>> import gbp.git
635     >>> bare = gbp.git.GitRepository.create(bare_dir, bare=True, description="msg")
636     >>> bare.path == bare_dir
637     True
638     >>> bare.git_dir[:-1] == bare_dir
639     True
640     >>> type(bare) == gbp.git.GitRepository
641     True
642     >>> bare.is_empty()
643     True
644     >>> bare.is_clean()
645     (True, '')
646     """
647
648 def test_nonexistant():
649     """
650     Check that accessing a non existant repository fails.
651
652     Methods tested:
653          - L{gbp.git.GitRepository.__init__}
654
655     >>> import gbp.git
656     >>> bare = gbp.git.GitRepository("/does/not/exist")
657     Traceback (most recent call last):
658     ...
659     GitRepositoryError: No Git repository at '/does/not/exist'
660     """
661
662 def test_create_noperm():
663     """
664     Check that creating a repository at a path that isn't writeable fails
665
666     Methods tested:
667          - L{gbp.git.GitRepository.create}
668
669     >>> import gbp.git
670     >>> gbp.git.GitRepository.create("/does/not/exist")
671     Traceback (most recent call last):
672     ...
673     GitRepositoryError: Cannot create Git repository at '/does/not/exist': Permission denied
674     """
675
676 def test_checkout():
677     """
678     Checkout treeishs
679
680     Methods tested:
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}
685
686     Properties tested:
687          - L{gbp.git.GitRepository.branch}
688          - L{gbp.git.GitRepository.tags}
689
690     >>> import gbp.git
691     >>> repo = gbp.git.GitRepository(repo_dir)
692     >>> repo.checkout('master')
693     >>> repo.branch
694     'master'
695     >>> repo.rev_parse('doesnotexist')
696     Traceback (most recent call last):
697     ...
698     GitRepositoryError: revision 'doesnotexist' not found
699     >>> sha1 = repo.rev_parse('master', short=10)
700     >>> len(sha1)
701     10
702     >>> sha1 = repo.rev_parse('master')
703     >>> len(sha1)
704     40
705     >>> repo.checkout(sha1)
706     >>> repo.branch
707     >>> repo.get_branch()
708     Traceback (most recent call last):
709     ...
710     GitRepositoryError: Currently not on a branch
711     >>> tag = repo.tags[0]
712     >>> repo.checkout(tag)
713     >>> repo.branch
714     """
715
716 def test_gc():
717     """
718     Test garbace collection
719
720     Methods tested:
721          - L{gbp.git.GitRepository.collect_garbage}
722
723     >>> import gbp.git
724     >>> repo = gbp.git.GitRepository(repo_dir)
725     >>> repo.collect_garbage()
726     """
727
728 def test_grep_log():
729     """
730     Test grepping through commit messages
731
732     Methods tested:
733         - L{gbp.git.GitRepository.grep_log}
734
735     >>> import gbp.git
736     >>> repo = gbp.git.GitRepository(repo_dir)
737     >>> repo.set_branch('master')
738     >>> len(repo.grep_log('foo')) == 2
739     True
740     >>> len(repo.grep_log('foo', 'master')) == 2
741     True
742     >>> repo.grep_log('blafasel')
743     []
744     >>> repo.grep_log('foo', 'doesnotexist')
745     Traceback (most recent call last):
746     ...
747     GitRepositoryError: Error grepping log for foo: fatal: bad revision 'doesnotexist'
748     """
749
750 def test_is_ff():
751     """
752     Test if branch is fast forwardable
753
754     Methods tested:
755         - L{gbp.git.GitRepository.is_fast_forward}
756
757     >>> import gbp.git
758     >>> repo = gbp.git.GitRepository(repo_dir)
759     >>> repo.is_fast_forward('master', 'foo')
760     (True, True)
761     >>> repo.create_branch('ff', 'HEAD^')
762     >>> repo.is_fast_forward('ff', 'master')
763     (True, False)
764     >>> repo.is_fast_forward('master', 'ff')
765     (False, True)
766     """
767
768 def test_update_ref():
769     """
770     Test updating a reference
771
772     Methods tested:
773         - L{gbp.git.GitRepository.update_ref}
774
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'))
779     True
780     """
781
782
783 def test_make_tree():
784     """
785     Test git-mk-tree
786
787     Methods tested:
788         - L{gbp.git.GitRepository.write_file}
789         - L{gbp.git.GitRepository.list_tree}
790         - L{gbp.git.GitRepository.make_tree}
791
792     >>> import gbp.git
793     >>> repo = gbp.git.GitRepository(repo_dir)
794     >>> sha1 = repo.write_file('testfile')
795     >>> sha1
796     '19af7398c894bc5e86e17259317e4db519e9241f'
797     >>> head = repo.list_tree('HEAD')
798     >>> head
799     [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
800     >>> head.append(['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile2'])
801     >>> repo.make_tree(head)
802     '745951810c9e22fcc6de9b23f05efd6ab5512123'
803     """
804
805
806 def test_update_submodules():
807     """
808     Updating submodules if we don't have any is a noop
809
810     Methods tested:
811         - L{gbp.git.GitRepository.has_submodules}
812         - L{gbp.git.GitRepository.update_submodules}
813
814     >>> import gbp.git
815     >>> repo = gbp.git.GitRepository(repo_dir)
816     >>> repo.has_submodules()
817     False
818     >>> repo.update_submodules()
819     """
820
821 def test_get_merge_base():
822     """
823     Find the common ancestor of two objects
824
825     Methods tested:
826         - L{gbp.git.GitRepository.get_merge_base}
827
828     >>> import gbp.git
829     >>> repo = gbp.git.GitRepository(repo_dir)
830     >>> sha1 = repo.get_merge_base('master', 'foo')
831     >>> len(sha1)
832     40
833     >>> repo.get_merge_base('master', 'doesnotexist')
834     Traceback (most recent call last):
835     ...
836     GitRepositoryError: Failed to get common ancestor: fatal: Not a valid object name doesnotexist
837     """
838
839 def test_cmd_has_feature():
840     r"""
841     Methods tested:
842         - L{gbp.git.GitRepository._cmd_has_feature}
843
844     >>> import gbp.git
845     >>> repo = gbp.git.GitRepository(repo_dir)
846     >>> repo._cmd_has_feature("commit", "a")
847     True
848     >>> repo._cmd_has_feature("commit", "reuse-message")
849     True
850     >>> repo._cmd_has_feature("merge", "n")
851     True
852     >>> repo._cmd_has_feature("merge", "stat")
853     True
854     >>> repo._cmd_has_feature("format-patch", "cc")
855     True
856     >>> repo._cmd_has_feature("merge", "foobaroption")
857     False
858     >>> repo._cmd_has_feature("foobarcmd", "foobaroption")
859     Traceback (most recent call last):
860     ...
861     GitRepositoryError: Invalid git command 'foobarcmd': No manual entry for gitfoobarcmd
862     >>> repo._cmd_has_feature("show", "standard-notes")
863     True
864     >>> repo._cmd_has_feature("show", "no-standard-notes")
865     True
866     """
867
868 def test_teardown():
869     """
870     Perform the teardown
871
872     >>> context.teardown()
873     """
874
875 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: