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.PreCommitHook;
58 import org.eclipse.jgit.junit.JGitTestUtil;
59 import org.eclipse.jgit.junit.RepositoryTestCase;
60 import org.eclipse.jgit.revwalk.RevCommit;
61 import org.junit.Assume;
62 import org.junit.Test;
63
64 public class HookTest extends RepositoryTestCase {
65
66 @Test
67 public void testFindHook() throws Exception {
68 assumeSupportedPlatform();
69
70 assertNull("no hook should be installed",
71 FS.DETECTED.findHook(db, PreCommitHook.NAME));
72 File hookFile = writeHookFile(PreCommitHook.NAME,
73 "#!/bin/bash\necho \"test $1 $2\"");
74 assertEquals("expected to find pre-commit hook", hookFile,
75 FS.DETECTED.findHook(db, PreCommitHook.NAME));
76 }
77
78 @Test
79 public void testFailedCommitMsgHookBlocksCommit() throws Exception {
80 assumeSupportedPlatform();
81
82 writeHookFile(CommitMsgHook.NAME,
83 "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
84 Git git = Git.wrap(db);
85 String path = "a.txt";
86 writeTrashFile(path, "content");
87 git.add().addFilepattern(path).call();
88 ByteArrayOutputStream out = new ByteArrayOutputStream();
89 try {
90 git.commit().setMessage("commit")
91 .setHookOutputStream(new PrintStream(out)).call();
92 fail("expected commit-msg hook to abort commit");
93 } catch (AbortedByHookException e) {
94 assertEquals("unexpected error message from commit-msg hook",
95 "Rejected by \"commit-msg\" hook.\nstderr\n",
96 e.getMessage());
97 assertEquals("unexpected output from commit-msg hook", "test\n",
98 out.toString());
99 }
100 }
101
102 @Test
103 public void testCommitMsgHookReceivesCorrectParameter() throws Exception {
104 assumeSupportedPlatform();
105
106 writeHookFile(CommitMsgHook.NAME,
107 "#!/bin/sh\necho $1\n\necho 1>&2 \"stderr\"\nexit 0");
108 Git git = Git.wrap(db);
109 String path = "a.txt";
110 writeTrashFile(path, "content");
111 git.add().addFilepattern(path).call();
112 ByteArrayOutputStream out = new ByteArrayOutputStream();
113 git.commit().setMessage("commit")
114 .setHookOutputStream(new PrintStream(out)).call();
115 assertEquals(".git/COMMIT_EDITMSG\n",
116 out.toString("UTF-8"));
117 }
118
119 @Test
120 public void testCommitMsgHookCanModifyCommitMessage() throws Exception {
121 assumeSupportedPlatform();
122
123 writeHookFile(CommitMsgHook.NAME,
124 "#!/bin/sh\necho \"new message\" > $1\nexit 0");
125 Git git = Git.wrap(db);
126 String path = "a.txt";
127 writeTrashFile(path, "content");
128 git.add().addFilepattern(path).call();
129 ByteArrayOutputStream out = new ByteArrayOutputStream();
130 RevCommit revCommit = git.commit().setMessage("commit")
131 .setHookOutputStream(new PrintStream(out)).call();
132 assertEquals("new message\n", revCommit.getFullMessage());
133 }
134
135 @Test
136 public void testRunHook() throws Exception {
137 assumeSupportedPlatform();
138
139 writeHookFile(PreCommitHook.NAME,
140 "#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
141 ByteArrayOutputStream out = new ByteArrayOutputStream();
142 ByteArrayOutputStream err = new ByteArrayOutputStream();
143 ProcessResult res = FS.DETECTED.runHookIfPresent(db,
144 PreCommitHook.NAME,
145 new String[] {
146 "arg1", "arg2" },
147 new PrintStream(out), new PrintStream(err), "stdin");
148
149 assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
150 out.toString("UTF-8"));
151 assertEquals("unexpected output on stderr stream", "stderr\n",
152 err.toString("UTF-8"));
153 assertEquals("unexpected exit code", 0, res.getExitCode());
154 assertEquals("unexpected process status", ProcessResult.Status.OK,
155 res.getStatus());
156 }
157
158 @Test
159 public void testFailedPreCommitHookBlockCommit() throws Exception {
160 assumeSupportedPlatform();
161
162 writeHookFile(PreCommitHook.NAME,
163 "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
164 Git git = Git.wrap(db);
165 String path = "a.txt";
166 writeTrashFile(path, "content");
167 git.add().addFilepattern(path).call();
168 ByteArrayOutputStream out = new ByteArrayOutputStream();
169 try {
170 git.commit().setMessage("commit")
171 .setHookOutputStream(new PrintStream(out)).call();
172 fail("expected pre-commit hook to abort commit");
173 } catch (AbortedByHookException e) {
174 assertEquals("unexpected error message from pre-commit hook",
175 "Rejected by \"pre-commit\" hook.\nstderr\n",
176 e.getMessage());
177 assertEquals("unexpected output from pre-commit hook", "test\n",
178 out.toString());
179 }
180 }
181
182 private File writeHookFile(final String name, final String data)
183 throws IOException {
184 File path = new File(db.getWorkTree() + "/.git/hooks/", name);
185 JGitTestUtil.write(path, data);
186 FS.DETECTED.setExecute(path, true);
187 return path;
188 }
189
190 private void assumeSupportedPlatform() {
191 Assume.assumeTrue(FS.DETECTED instanceof FS_POSIX
192 || FS.DETECTED instanceof FS_Win32_Cygwin);
193 }
194 }