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
44
45
46
47
48 package org.eclipse.jgit.transport;
49
50 import java.io.BufferedInputStream;
51 import java.io.BufferedOutputStream;
52 import java.io.File;
53 import java.io.IOException;
54 import java.io.InputStream;
55 import java.io.OutputStream;
56 import java.util.Collections;
57 import java.util.Map;
58 import java.util.Set;
59
60 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
61 import org.eclipse.jgit.errors.NotSupportedException;
62 import org.eclipse.jgit.errors.TransportException;
63 import org.eclipse.jgit.internal.JGitText;
64 import org.eclipse.jgit.lib.Repository;
65 import org.eclipse.jgit.lib.RepositoryBuilder;
66 import org.eclipse.jgit.lib.RepositoryCache;
67 import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
68 import org.eclipse.jgit.transport.resolver.UploadPackFactory;
69 import org.eclipse.jgit.util.FS;
70 import org.eclipse.jgit.util.io.MessageWriter;
71 import org.eclipse.jgit.util.io.StreamCopyThread;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 class TransportLocal extends Transport implements PackTransport {
97 static final TransportProtocol PROTO_LOCAL = new TransportProtocol() {
98 @Override
99 public String getName() {
100 return JGitText.get().transportProtoLocal;
101 }
102
103 @Override
104 public Set<String> getSchemes() {
105 return Collections.singleton("file");
106 }
107
108 @Override
109 public boolean canHandle(URIish uri, Repository local, String remoteName) {
110 if (uri.getPath() == null
111 || uri.getPort() > 0
112 || uri.getUser() != null
113 || uri.getPass() != null
114 || uri.getHost() != null
115 || (uri.getScheme() != null && !getSchemes().contains(uri.getScheme())))
116 return false;
117 return true;
118 }
119
120 @Override
121 public Transport open(URIish uri, Repository local, String remoteName)
122 throws NoRemoteRepositoryException {
123 File localPath = local.isBare() ? local.getDirectory() : local.getWorkTree();
124 File path = local.getFS().resolve(localPath, uri.getPath());
125
126
127 if (path.isFile())
128 return new TransportBundleFile(local, uri, path);
129
130 File gitDir = RepositoryCache.FileKey.resolve(path, local.getFS());
131 if (gitDir == null)
132 throw new NoRemoteRepositoryException(uri, JGitText.get().notFound);
133 return new TransportLocal(local, uri, gitDir);
134 }
135
136 @Override
137 public Transport open(URIish uri) throws NotSupportedException,
138 TransportException {
139 File path = FS.DETECTED.resolve(new File("."), uri.getPath());
140
141
142 if (path.isFile())
143 return new TransportBundleFile(uri, path);
144
145 File gitDir = RepositoryCache.FileKey.resolve(path, FS.DETECTED);
146 if (gitDir == null)
147 throw new NoRemoteRepositoryException(uri,
148 JGitText.get().notFound);
149 return new TransportLocal(uri, gitDir);
150 }
151 };
152
153 private final File remoteGitDir;
154
155 TransportLocal(Repository local, URIish uri, File gitDir) {
156 super(local, uri);
157 remoteGitDir = gitDir;
158 }
159
160 TransportLocal(URIish uri, File gitDir) {
161 super(uri);
162 remoteGitDir = gitDir;
163 }
164
165 UploadPack createUploadPack(final Repository dst) {
166 return new UploadPack(dst);
167 }
168
169 ReceivePack createReceivePack(final Repository dst) {
170 return new ReceivePack(dst);
171 }
172
173 private Repository openRepo() throws TransportException {
174 try {
175 return new RepositoryBuilder().setGitDir(remoteGitDir).build();
176 } catch (IOException err) {
177 throw new TransportException(uri, JGitText.get().notAGitDirectory);
178 }
179 }
180
181 @Override
182 public FetchConnection openFetch() throws TransportException {
183 final String up = getOptionUploadPack();
184 if (!"git-upload-pack".equals(up)
185 && !"git upload-pack".equals(up))
186 return new ForkLocalFetchConnection();
187
188 UploadPackFactory<Void> upf = new UploadPackFactory<Void>() {
189 @Override
190 public UploadPack create(Void req, Repository db) {
191 return createUploadPack(db);
192 }
193 };
194 return new InternalFetchConnection<>(this, upf, null, openRepo());
195 }
196
197 @Override
198 public PushConnection openPush() throws TransportException {
199 final String rp = getOptionReceivePack();
200 if (!"git-receive-pack".equals(rp)
201 && !"git receive-pack".equals(rp))
202 return new ForkLocalPushConnection();
203
204 ReceivePackFactory<Void> rpf = new ReceivePackFactory<Void>() {
205 @Override
206 public ReceivePack create(Void req, Repository db) {
207 return createReceivePack(db);
208 }
209 };
210 return new InternalPushConnection<>(this, rpf, null, openRepo());
211 }
212
213 @Override
214 public void close() {
215
216 }
217
218 protected Process spawn(final String cmd)
219 throws TransportException {
220 try {
221 String[] args = { "." };
222 ProcessBuilder proc = local.getFS().runInShell(cmd, args);
223 proc.directory(remoteGitDir);
224
225
226 Map<String, String> env = proc.environment();
227 env.remove("GIT_ALTERNATE_OBJECT_DIRECTORIES");
228 env.remove("GIT_CONFIG");
229 env.remove("GIT_CONFIG_PARAMETERS");
230 env.remove("GIT_DIR");
231 env.remove("GIT_WORK_TREE");
232 env.remove("GIT_GRAFT_FILE");
233 env.remove("GIT_INDEX_FILE");
234 env.remove("GIT_NO_REPLACE_OBJECTS");
235
236 return proc.start();
237 } catch (IOException err) {
238 throw new TransportException(uri, err.getMessage(), err);
239 }
240 }
241
242 class ForkLocalFetchConnection extends BasePackFetchConnection {
243 private Process uploadPack;
244
245 private Thread errorReaderThread;
246
247 ForkLocalFetchConnection() throws TransportException {
248 super(TransportLocal.this);
249
250 final MessageWriter msg = new MessageWriter();
251 setMessageWriter(msg);
252
253 uploadPack = spawn(getOptionUploadPack());
254
255 final InputStream upErr = uploadPack.getErrorStream();
256 errorReaderThread = new StreamCopyThread(upErr, msg.getRawStream());
257 errorReaderThread.start();
258
259 InputStream upIn = uploadPack.getInputStream();
260 OutputStream upOut = uploadPack.getOutputStream();
261
262 upIn = new BufferedInputStream(upIn);
263 upOut = new BufferedOutputStream(upOut);
264
265 init(upIn, upOut);
266 readAdvertisedRefs();
267 }
268
269 @Override
270 public void close() {
271 super.close();
272
273 if (uploadPack != null) {
274 try {
275 uploadPack.waitFor();
276 } catch (InterruptedException ie) {
277
278 } finally {
279 uploadPack = null;
280 }
281 }
282
283 if (errorReaderThread != null) {
284 try {
285 errorReaderThread.join();
286 } catch (InterruptedException e) {
287
288 } finally {
289 errorReaderThread = null;
290 }
291 }
292 }
293 }
294
295 class ForkLocalPushConnection extends BasePackPushConnection {
296 private Process receivePack;
297
298 private Thread errorReaderThread;
299
300 ForkLocalPushConnection() throws TransportException {
301 super(TransportLocal.this);
302
303 final MessageWriter msg = new MessageWriter();
304 setMessageWriter(msg);
305
306 receivePack = spawn(getOptionReceivePack());
307
308 final InputStream rpErr = receivePack.getErrorStream();
309 errorReaderThread = new StreamCopyThread(rpErr, msg.getRawStream());
310 errorReaderThread.start();
311
312 InputStream rpIn = receivePack.getInputStream();
313 OutputStream rpOut = receivePack.getOutputStream();
314
315 rpIn = new BufferedInputStream(rpIn);
316 rpOut = new BufferedOutputStream(rpOut);
317
318 init(rpIn, rpOut);
319 readAdvertisedRefs();
320 }
321
322 @Override
323 public void close() {
324 super.close();
325
326 if (receivePack != null) {
327 try {
328 receivePack.waitFor();
329 } catch (InterruptedException ie) {
330
331 } finally {
332 receivePack = null;
333 }
334 }
335
336 if (errorReaderThread != null) {
337 try {
338 errorReaderThread.join();
339 } catch (InterruptedException e) {
340
341 } finally {
342 errorReaderThread = null;
343 }
344 }
345 }
346 }
347 }