1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.util;
44
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertNull;
47 import static org.junit.Assert.fail;
48
49 import java.io.ByteArrayOutputStream;
50 import java.io.File;
51 import java.io.IOException;
52 import java.io.PrintStream;
53
54 import org.eclipse.jgit.api.Git;
55 import org.eclipse.jgit.api.errors.AbortedByHookException;
56 import org.eclipse.jgit.hooks.CommitMsgHook;
57 import org.eclipse.jgit.hooks.PostCommitHook;
58 import org.eclipse.jgit.hooks.PreCommitHook;
59 import org.eclipse.jgit.junit.JGitTestUtil;
60 import org.eclipse.jgit.junit.RepositoryTestCase;
61 import org.eclipse.jgit.revwalk.RevCommit;
62 import org.junit.Assume;
63 import org.junit.Test;
64
65 public class HookTest extends RepositoryTestCase {
66
67 @Test
68 public void testFindHook() throws Exception {
69 assumeSupportedPlatform();
70
71 assertNull("no hook should be installed",
72 FS.DETECTED.findHook(db, PreCommitHook.NAME));
73 File hookFile = writeHookFile(PreCommitHook.NAME,
74 "#!/bin/bash\necho \"test $1 $2\"");
75 assertEquals("expected to find pre-commit hook", hookFile,
76 FS.DETECTED.findHook(db, PreCommitHook.NAME));
77 }
78
79 @Test
80 public void testFindPostCommitHook() throws Exception {
81 assumeSupportedPlatform();
82
83 assertNull("no hook should be installed",
84 FS.DETECTED.findHook(db, PostCommitHook.NAME));
85 File hookFile = writeHookFile(PostCommitHook.NAME,
86 "#!/bin/bash\necho \"test $1 $2\"");
87 assertEquals("expected to find post-commit hook", hookFile,
88 FS.DETECTED.findHook(db, PostCommitHook.NAME));
89 }
90
91 @Test
92 public void testFailedCommitMsgHookBlocksCommit() throws Exception {
93 assumeSupportedPlatform();
94
95 writeHookFile(CommitMsgHook.NAME,
96 "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
97 Git git = Git.wrap(db);
98 String path = "a.txt";
99 writeTrashFile(path, "content");
100 git.add().addFilepattern(path).call();
101 ByteArrayOutputStream out = new ByteArrayOutputStream();
102 try {
103 git.commit().setMessage("commit")
104 .setHookOutputStream(new PrintStream(out)).call();
105 fail("expected commit-msg hook to abort commit");
106 } catch (AbortedByHookException e) {
107 assertEquals("unexpected error message from commit-msg hook",
108 "Rejected by \"commit-msg\" hook.\nstderr\n",
109 e.getMessage());
110 assertEquals("unexpected output from commit-msg hook", "test\n",
111 out.toString());
112 }
113 }
114
115 @Test
116 public void testCommitMsgHookReceivesCorrectParameter() throws Exception {
117 assumeSupportedPlatform();
118
119 writeHookFile(CommitMsgHook.NAME,
120 "#!/bin/sh\necho $1\n\necho 1>&2 \"stderr\"\nexit 0");
121 Git git = Git.wrap(db);
122 String path = "a.txt";
123 writeTrashFile(path, "content");
124 git.add().addFilepattern(path).call();
125 ByteArrayOutputStream out = new ByteArrayOutputStream();
126 git.commit().setMessage("commit")
127 .setHookOutputStream(new PrintStream(out)).call();
128 assertEquals(".git/COMMIT_EDITMSG\n",
129 out.toString("UTF-8"));
130 }
131
132 @Test
133 public void testCommitMsgHookCanModifyCommitMessage() throws Exception {
134 assumeSupportedPlatform();
135
136 writeHookFile(CommitMsgHook.NAME,
137 "#!/bin/sh\necho \"new message\" > $1\nexit 0");
138 Git git = Git.wrap(db);
139 String path = "a.txt";
140 writeTrashFile(path, "content");
141 git.add().addFilepattern(path).call();
142 ByteArrayOutputStream out = new ByteArrayOutputStream();
143 RevCommit revCommit = git.commit().setMessage("commit")
144 .setHookOutputStream(new PrintStream(out)).call();
145 assertEquals("new message\n", revCommit.getFullMessage());
146 }
147
148 @Test
149 public void testPostCommitRunHook() throws Exception {
150 assumeSupportedPlatform();
151
152 writeHookFile(PostCommitHook.NAME,
153 "#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
154 ByteArrayOutputStream out = new ByteArrayOutputStream();
155 ByteArrayOutputStream err = new ByteArrayOutputStream();
156 ProcessResult res = FS.DETECTED.runHookIfPresent(db,
157 PostCommitHook.NAME,
158 new String[] {
159 "arg1", "arg2" },
160 new PrintStream(out), new PrintStream(err), "stdin");
161
162 assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
163 out.toString("UTF-8"));
164 assertEquals("unexpected output on stderr stream", "stderr\n",
165 err.toString("UTF-8"));
166 assertEquals("unexpected exit code", 0, res.getExitCode());
167 assertEquals("unexpected process status", ProcessResult.Status.OK,
168 res.getStatus());
169 }
170
171 @Test
172 public void testAllCommitHooks() throws Exception {
173 assumeSupportedPlatform();
174
175 writeHookFile(PreCommitHook.NAME,
176 "#!/bin/sh\necho \"test pre-commit\"\n\necho 1>&2 \"stderr pre-commit\"\nexit 0");
177 writeHookFile(CommitMsgHook.NAME,
178 "#!/bin/sh\necho \"test commit-msg $1\"\n\necho 1>&2 \"stderr commit-msg\"\nexit 0");
179 writeHookFile(PostCommitHook.NAME,
180 "#!/bin/sh\necho \"test post-commit\"\necho 1>&2 \"stderr post-commit\"\nexit 0");
181 Git git = Git.wrap(db);
182 String path = "a.txt";
183 writeTrashFile(path, "content");
184 git.add().addFilepattern(path).call();
185 ByteArrayOutputStream out = new ByteArrayOutputStream();
186 try {
187 git.commit().setMessage("commit")
188 .setHookOutputStream(new PrintStream(out)).call();
189 } catch (AbortedByHookException e) {
190 fail("unexpected hook failure");
191 }
192 assertEquals("unexpected hook output",
193 "test pre-commit\ntest commit-msg .git/COMMIT_EDITMSG\ntest post-commit\n",
194 out.toString("UTF-8"));
195 }
196
197 @Test
198 public void testRunHook() throws Exception {
199 assumeSupportedPlatform();
200
201 writeHookFile(PreCommitHook.NAME,
202 "#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
203 ByteArrayOutputStream out = new ByteArrayOutputStream();
204 ByteArrayOutputStream err = new ByteArrayOutputStream();
205 ProcessResult res = FS.DETECTED.runHookIfPresent(db,
206 PreCommitHook.NAME,
207 new String[] {
208 "arg1", "arg2" },
209 new PrintStream(out), new PrintStream(err), "stdin");
210
211 assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
212 out.toString("UTF-8"));
213 assertEquals("unexpected output on stderr stream", "stderr\n",
214 err.toString("UTF-8"));
215 assertEquals("unexpected exit code", 0, res.getExitCode());
216 assertEquals("unexpected process status", ProcessResult.Status.OK,
217 res.getStatus());
218 }
219
220 @Test
221 public void testFailedPreCommitHookBlockCommit() throws Exception {
222 assumeSupportedPlatform();
223
224 writeHookFile(PreCommitHook.NAME,
225 "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
226 Git git = Git.wrap(db);
227 String path = "a.txt";
228 writeTrashFile(path, "content");
229 git.add().addFilepattern(path).call();
230 ByteArrayOutputStream out = new ByteArrayOutputStream();
231 try {
232 git.commit().setMessage("commit")
233 .setHookOutputStream(new PrintStream(out)).call();
234 fail("expected pre-commit hook to abort commit");
235 } catch (AbortedByHookException e) {
236 assertEquals("unexpected error message from pre-commit hook",
237 "Rejected by \"pre-commit\" hook.\nstderr\n",
238 e.getMessage());
239 assertEquals("unexpected output from pre-commit hook", "test\n",
240 out.toString());
241 }
242 }
243
244 private File writeHookFile(final String name, final String data)
245 throws IOException {
246 File path = new File(db.getWorkTree() + "/.git/hooks/", name);
247 JGitTestUtil.write(path, data);
248 FS.DETECTED.setExecute(path, true);
249 return path;
250 }
251
252 private void assumeSupportedPlatform() {
253 Assume.assumeTrue(FS.DETECTED instanceof FS_POSIX
254 || FS.DETECTED instanceof FS_Win32_Cygwin);
255 }
256 }