Dulwich.io dulwich / d94c58a
Add shell hook tests milki 6 years ago
4 changed file(s) with 321 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
116116 'diff_tree',
117117 'fastexport',
118118 'file',
119 'hooks',
119120 'index',
120121 'lru_cache',
121122 'objects',
0 # test_hooks.py -- Tests for executing hooks
1 #
2 # This program is free software; you can redistribute it and/or
3 # modify it under the terms of the GNU General Public License
4 # as published by the Free Software Foundation; either version 2
5 # or (at your option) a later version of the License.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15 # MA 02110-1301, USA.
16
17 """Tests for executing hooks."""
18
19 import os
20 import stat
21 import shutil
22 import tempfile
23 import warnings
24
25 from dulwich import errors
26
27 from dulwich.hooks import (
28 PreCommitShellHook,
29 PostCommitShellHook,
30 CommitMsgShellHook,
31 )
32
33 from dulwich.tests import TestCase
34
35
36 class ShellHookTests(TestCase):
37
38 def setUp(self):
39 if os.name != 'posix':
40 self.skipTest('shell hook tests requires POSIX shell')
41
42 def test_hook_pre_commit(self):
43 pre_commit_fail = """#!/bin/sh
44 exit 1
45 """
46
47 pre_commit_success = """#!/bin/sh
48 exit 0
49 """
50
51 repo_dir = os.path.join(tempfile.mkdtemp())
52 os.mkdir(os.path.join(repo_dir, 'hooks'))
53 self.addCleanup(shutil.rmtree, repo_dir)
54
55 pre_commit = os.path.join(repo_dir, 'hooks', 'pre-commit')
56 hook = PreCommitShellHook(repo_dir)
57
58 f = open(pre_commit, 'wb')
59 try:
60 f.write(pre_commit_fail)
61 finally:
62 f.close()
63 os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
64
65 self.assertRaises(errors.HookError, hook.execute)
66
67 f = open(pre_commit, 'wb')
68 try:
69 f.write(pre_commit_success)
70 finally:
71 f.close()
72 os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
73
74 hook.execute()
75
76 def test_hook_commit_msg(self):
77
78 commit_msg_fail = """#!/bin/sh
79 exit 1
80 """
81
82 commit_msg_success = """#!/bin/sh
83 exit 0
84 """
85
86 repo_dir = os.path.join(tempfile.mkdtemp())
87 os.mkdir(os.path.join(repo_dir, 'hooks'))
88 self.addCleanup(shutil.rmtree, repo_dir)
89
90 commit_msg = os.path.join(repo_dir, 'hooks', 'commit-msg')
91 hook = CommitMsgShellHook(repo_dir)
92
93 f = open(commit_msg, 'wb')
94 try:
95 f.write(commit_msg_fail)
96 finally:
97 f.close()
98 os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
99
100 self.assertRaises(errors.HookError, hook.execute, 'failed commit')
101
102 f = open(commit_msg, 'wb')
103 try:
104 f.write(commit_msg_success)
105 finally:
106 f.close()
107 os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
108
109 hook.execute('empty commit')
110
111 def test_hook_post_commit(self):
112
113 (fd, path) = tempfile.mkstemp()
114 post_commit_msg = """#!/bin/sh
115 unlink %(file)s
116 """ % {'file': path}
117
118 post_commit_msg_fail = """#!/bin/sh
119 exit 1
120 """
121
122 repo_dir = os.path.join(tempfile.mkdtemp())
123 os.mkdir(os.path.join(repo_dir, 'hooks'))
124 self.addCleanup(shutil.rmtree, repo_dir)
125
126 post_commit = os.path.join(repo_dir, 'hooks', 'post-commit')
127 hook = PostCommitShellHook(repo_dir)
128
129 f = open(post_commit, 'wb')
130 try:
131 f.write(post_commit_msg_fail)
132 finally:
133 f.close()
134 os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
135
136 self.assertRaises(errors.HookError, hook.execute)
137
138 f = open(post_commit, 'wb')
139 try:
140 f.write(post_commit_msg)
141 finally:
142 f.close()
143 os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
144
145 hook.execute()
146 self.assertFalse(os.path.exists(path))
2020
2121 from cStringIO import StringIO
2222 import os
23 import stat
2324 import shutil
2425 import tempfile
2526 import warnings
5051 from dulwich.tests.utils import (
5152 open_repo,
5253 tear_down_repo,
54 setup_warning_catcher,
5355 )
5456
5557 missing_sha = 'b91fa4d900e17e99b433218e988c4eb4a3e9a097'
410412 finally:
411413 shutil.rmtree(r1_dir)
412414 shutil.rmtree(r2_dir)
415
416 def test_shell_hook_pre_commit(self):
417 if os.name != 'posix':
418 self.skipTest('shell hook tests requires POSIX shell')
419
420 pre_commit_fail = """#!/bin/sh
421 exit 1
422 """
423
424 pre_commit_success = """#!/bin/sh
425 exit 0
426 """
427
428 repo_dir = os.path.join(tempfile.mkdtemp())
429 r = Repo.init(repo_dir)
430 self.addCleanup(shutil.rmtree, repo_dir)
431
432 pre_commit = os.path.join(r.controldir(), 'hooks', 'pre-commit')
433
434 f = open(pre_commit, 'wb')
435 try:
436 f.write(pre_commit_fail)
437 finally:
438 f.close()
439 os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
440
441 self.assertRaises(errors.CommitError, r.do_commit, 'failed commit',
442 committer='Test Committer <test@nodomain.com>',
443 author='Test Author <test@nodomain.com>',
444 commit_timestamp=12345, commit_timezone=0,
445 author_timestamp=12345, author_timezone=0)
446
447 f = open(pre_commit, 'wb')
448 try:
449 f.write(pre_commit_success)
450 finally:
451 f.close()
452 os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
453
454 commit_sha = r.do_commit(
455 'empty commit',
456 committer='Test Committer <test@nodomain.com>',
457 author='Test Author <test@nodomain.com>',
458 commit_timestamp=12395, commit_timezone=0,
459 author_timestamp=12395, author_timezone=0)
460 self.assertEqual([], r[commit_sha].parents)
461
462 def test_shell_hook_commit_msg(self):
463 if os.name != 'posix':
464 self.skipTest('shell hook tests requires POSIX shell')
465
466 commit_msg_fail = """#!/bin/sh
467 exit 1
468 """
469
470 commit_msg_success = """#!/bin/sh
471 exit 0
472 """
473
474 repo_dir = os.path.join(tempfile.mkdtemp())
475 r = Repo.init(repo_dir)
476 self.addCleanup(shutil.rmtree, repo_dir)
477
478 commit_msg = os.path.join(r.controldir(), 'hooks', 'commit-msg')
479
480 f = open(commit_msg, 'wb')
481 try:
482 f.write(commit_msg_fail)
483 finally:
484 f.close()
485 os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
486
487 self.assertRaises(errors.CommitError, r.do_commit, 'failed commit',
488 committer='Test Committer <test@nodomain.com>',
489 author='Test Author <test@nodomain.com>',
490 commit_timestamp=12345, commit_timezone=0,
491 author_timestamp=12345, author_timezone=0)
492
493 f = open(commit_msg, 'wb')
494 try:
495 f.write(commit_msg_success)
496 finally:
497 f.close()
498 os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
499
500 commit_sha = r.do_commit(
501 'empty commit',
502 committer='Test Committer <test@nodomain.com>',
503 author='Test Author <test@nodomain.com>',
504 commit_timestamp=12395, commit_timezone=0,
505 author_timestamp=12395, author_timezone=0)
506 self.assertEqual([], r[commit_sha].parents)
507
508 def test_shell_hook_post_commit(self):
509 if os.name != 'posix':
510 self.skipTest('shell hook tests requires POSIX shell')
511
512 repo_dir = os.path.join(tempfile.mkdtemp())
513 r = Repo.init(repo_dir)
514 self.addCleanup(shutil.rmtree, repo_dir)
515
516 (fd, path) = tempfile.mkstemp(dir=repo_dir)
517 post_commit_msg = """#!/bin/sh
518 unlink %(file)s
519 """ % {'file': path}
520
521 root_sha = r.do_commit(
522 'empty commit',
523 committer='Test Committer <test@nodomain.com>',
524 author='Test Author <test@nodomain.com>',
525 commit_timestamp=12345, commit_timezone=0,
526 author_timestamp=12345, author_timezone=0)
527 self.assertEqual([], r[root_sha].parents)
528
529 post_commit = os.path.join(r.controldir(), 'hooks', 'post-commit')
530
531 f = open(post_commit, 'wb')
532 try:
533 f.write(post_commit_msg)
534 finally:
535 f.close()
536 os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
537
538 commit_sha = r.do_commit(
539 'empty commit',
540 committer='Test Committer <test@nodomain.com>',
541 author='Test Author <test@nodomain.com>',
542 commit_timestamp=12345, commit_timezone=0,
543 author_timestamp=12345, author_timezone=0)
544 self.assertEqual([root_sha], r[commit_sha].parents)
545
546 self.assertFalse(os.path.exists(path))
547
548 post_commit_msg_fail = """#!/bin/sh
549 exit 1
550 """
551 f = open(post_commit, 'wb')
552 try:
553 f.write(post_commit_msg_fail)
554 finally:
555 f.close()
556 os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
557
558 warnings.simplefilter("always", UserWarning)
559 self.addCleanup(warnings.resetwarnings)
560 warnings_list = setup_warning_catcher()
561
562 commit_sha2 = r.do_commit(
563 'empty commit',
564 committer='Test Committer <test@nodomain.com>',
565 author='Test Author <test@nodomain.com>',
566 commit_timestamp=12345, commit_timezone=0,
567 author_timestamp=12345, author_timezone=0)
568 self.assertEqual(len(warnings_list), 1)
569 self.assertIsInstance(warnings_list[-1], UserWarning)
570 self.assertTrue("post-commit hook failed: " in str(warnings_list[-1]))
571 self.assertEqual([commit_sha], r[commit_sha2].parents)
413572
414573
415574 class BuildRepoTests(TestCase):
2525 import tempfile
2626 import time
2727 import types
28 import warnings
2829
2930 from dulwich.index import (
3031 commit_tree,
309310 commits.append(commit_obj)
310311
311312 return commits
313
314
315 def setup_warning_catcher():
316 """Wrap warnings.showwarning with code that records warnings."""
317
318 caught_warnings = []
319 original_showwarning = warnings.showwarning
320
321 def custom_showwarning(*args, **kwargs):
322 caught_warnings.append(args[0])
323
324 warnings.showwarning = custom_showwarning
325 return caught_warnings