View Javadoc
1   /*
2    * Copyright (C) 2010, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.http.test;
12  
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertNotNull;
15  import static org.junit.Assert.assertTrue;
16  
17  import java.io.ByteArrayOutputStream;
18  import java.io.OutputStream;
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.List;
22  
23  import javax.servlet.http.HttpServletRequest;
24  
25  import org.eclipse.jetty.servlet.ServletContextHandler;
26  import org.eclipse.jetty.servlet.ServletHolder;
27  import org.eclipse.jgit.errors.RepositoryNotFoundException;
28  import org.eclipse.jgit.http.server.GitServlet;
29  import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
30  import org.eclipse.jgit.junit.TestRepository;
31  import org.eclipse.jgit.junit.http.AccessEvent;
32  import org.eclipse.jgit.lib.Constants;
33  import org.eclipse.jgit.lib.NullProgressMonitor;
34  import org.eclipse.jgit.lib.ObjectId;
35  import org.eclipse.jgit.lib.Repository;
36  import org.eclipse.jgit.lib.StoredConfig;
37  import org.eclipse.jgit.revwalk.RevBlob;
38  import org.eclipse.jgit.revwalk.RevCommit;
39  import org.eclipse.jgit.transport.PushResult;
40  import org.eclipse.jgit.transport.ReceiveCommand;
41  import org.eclipse.jgit.transport.ReceivePack;
42  import org.eclipse.jgit.transport.RemoteRefUpdate;
43  import org.eclipse.jgit.transport.Transport;
44  import org.eclipse.jgit.transport.URIish;
45  import org.eclipse.jgit.transport.http.HttpConnectionFactory;
46  import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
47  import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
48  import org.junit.Before;
49  import org.junit.Test;
50  
51  public class HookMessageTest extends AllFactoriesHttpTestCase {
52  
53  	private Repository remoteRepository;
54  
55  	private URIish remoteURI;
56  
57  	public HookMessageTest(HttpConnectionFactory cf) {
58  		super(cf);
59  	}
60  
61  	@Override
62  	@Before
63  	public void setUp() throws Exception {
64  		super.setUp();
65  
66  		final TestRepository<Repository> src = createTestRepository();
67  		final String srcName = src.getRepository().getDirectory().getName();
68  
69  		ServletContextHandler app = server.addContext("/git");
70  		GitServlet gs = new GitServlet();
71  		gs.setRepositoryResolver((HttpServletRequest req, String name) -> {
72  			if (!name.equals(srcName)) {
73  				throw new RepositoryNotFoundException(name);
74  			}
75  			final Repository db = src.getRepository();
76  			db.incrementOpen();
77  			return db;
78  		});
79  		gs.setReceivePackFactory(new DefaultReceivePackFactory() {
80  			@Override
81  			public ReceivePack create(HttpServletRequest req, Repository db)
82  					throws ServiceNotEnabledException,
83  					ServiceNotAuthorizedException {
84  				ReceivePack recv = super.create(req, db);
85  				recv.setPreReceiveHook((ReceivePack rp,
86  						Collection<ReceiveCommand> commands) -> {
87  					rp.sendMessage("message line 1");
88  					rp.sendError("no soup for you!");
89  					rp.sendMessage("come back next year!");
90  				});
91  				return recv;
92  			}
93  
94  		});
95  		app.addServlet(new ServletHolder(gs), "/*");
96  
97  		server.setUp();
98  
99  		remoteRepository = src.getRepository();
100 		remoteURI = toURIish(app, srcName);
101 
102 		StoredConfig cfg = remoteRepository.getConfig();
103 		cfg.setBoolean("http", null, "receivepack", true);
104 		cfg.save();
105 	}
106 
107 	@Test
108 	public void testPush_CreateBranch() throws Exception {
109 		final TestRepository src = createTestRepository();
110 		final RevBlob Q_txt = src.blob("new text");
111 		final RevCommit Q = src.commit().add("Q", Q_txt).create();
112 		final Repository db = src.getRepository();
113 		final String dstName = Constants.R_HEADS + "new.branch";
114 		PushResult result;
115 
116 		try (Transport t = Transport.open(db, remoteURI)) {
117 			final String srcExpr = Q.name();
118 			final boolean forceUpdate = false;
119 			final String localName = null;
120 			final ObjectId oldId = null;
121 
122 			RemoteRefUpdate update = new RemoteRefUpdate(src.getRepository(),
123 					srcExpr, dstName, forceUpdate, localName, oldId);
124 			result = t.push(NullProgressMonitor.INSTANCE, Collections
125 					.singleton(update));
126 		}
127 
128 		assertTrue(remoteRepository.getObjectDatabase().has(Q_txt));
129 		assertNotNull("has " + dstName, remoteRepository.exactRef(dstName));
130 		assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
131 		fsck(remoteRepository, Q);
132 
133 		List<AccessEvent> requests = getRequests();
134 		assertEquals(2, requests.size());
135 
136 		AccessEvent service = requests.get(1);
137 		assertEquals("POST", service.getMethod());
138 		assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
139 		assertEquals(200, service.getStatus());
140 
141 		assertEquals("message line 1\n" //
142 				+ "error: no soup for you!\n" //
143 				+ "come back next year!\n", //
144 				result.getMessages());
145 	}
146 
147 	@Test
148 	public void testPush_HookMessagesToOutputStream() throws Exception {
149 		final TestRepository src = createTestRepository();
150 		final RevBlob Q_txt = src.blob("new text");
151 		final RevCommit Q = src.commit().add("Q", Q_txt).create();
152 		final Repository db = src.getRepository();
153 		final String dstName = Constants.R_HEADS + "new.branch";
154 		PushResult result;
155 
156 		OutputStream out = new ByteArrayOutputStream();
157 		try (Transport t = Transport.open(db, remoteURI)) {
158 			final String srcExpr = Q.name();
159 			final boolean forceUpdate = false;
160 			final String localName = null;
161 			final ObjectId oldId = null;
162 
163 			RemoteRefUpdate update = new RemoteRefUpdate(src.getRepository(),
164 					srcExpr, dstName, forceUpdate, localName, oldId);
165 			result = t.push(NullProgressMonitor.INSTANCE,
166 					Collections.singleton(update), out);
167 		}
168 
169 		String expectedMessage = "message line 1\n" //
170 				+ "error: no soup for you!\n" //
171 				+ "come back next year!\n";
172 		assertEquals(expectedMessage, //
173 				result.getMessages());
174 
175 		assertEquals(expectedMessage, out.toString());
176 	}
177 
178 }