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(Repository dst) {
166 return new UploadPack(dst);
167 }
168
169 ReceivePack createReceivePack(Repository dst) {
170 return new ReceivePack(dst);
171 }
172
173 private Repository openRepo() throws TransportException {
174 try {
175 return new RepositoryBuilder()
176 .setFS(local != null ? local.getFS() : FS.DETECTED)
177 .setGitDir(remoteGitDir).build();
178 } catch (IOException err) {
179 throw new TransportException(uri, JGitText.get().notAGitDirectory);
180 }
181 }
182
183
184 @Override
185 public FetchConnection openFetch() throws TransportException {
186 final String up = getOptionUploadPack();
187 if (!"git-upload-pack".equals(up)
188 && !"git upload-pack".equals(up))
189 return new ForkLocalFetchConnection();
190
191 UploadPackFactory<Void> upf = new UploadPackFactory<Void>() {
192 @Override
193 public UploadPack create(Void req, Repository db) {
194 return createUploadPack(db);
195 }
196 };
197 return new InternalFetchConnection<>(this, upf, null, openRepo());
198 }
199
200
201 @Override
202 public PushConnection openPush() throws TransportException {
203 final String rp = getOptionReceivePack();
204 if (!"git-receive-pack".equals(rp)
205 && !"git receive-pack".equals(rp))
206 return new ForkLocalPushConnection();
207
208 ReceivePackFactory<Void> rpf = new ReceivePackFactory<Void>() {
209 @Override
210 public ReceivePack create(Void req, Repository db) {
211 return createReceivePack(db);
212 }
213 };
214 return new InternalPushConnection<>(this, rpf, null, openRepo());
215 }
216
217
218 @Override
219 public void close() {
220
221 }
222
223
224
225
226
227
228
229
230
231
232 protected Process spawn(String cmd)
233 throws TransportException {
234 try {
235 String[] args = { "." };
236 ProcessBuilder proc = local.getFS().runInShell(cmd, args);
237 proc.directory(remoteGitDir);
238
239
240 Map<String, String> env = proc.environment();
241 env.remove("GIT_ALTERNATE_OBJECT_DIRECTORIES");
242 env.remove("GIT_CONFIG");
243 env.remove("GIT_CONFIG_PARAMETERS");
244 env.remove("GIT_DIR");
245 env.remove("GIT_WORK_TREE");
246 env.remove("GIT_GRAFT_FILE");
247 env.remove("GIT_INDEX_FILE");
248 env.remove("GIT_NO_REPLACE_OBJECTS");
249
250 return proc.start();
251 } catch (IOException err) {
252 throw new TransportException(uri, err.getMessage(), err);
253 }
254 }
255
256 class ForkLocalFetchConnection extends BasePackFetchConnection {
257 private Process uploadPack;
258
259 private Thread errorReaderThread;
260
261 ForkLocalFetchConnection() throws TransportException {
262 super(TransportLocal.this);
263
264 final MessageWriter msg = new MessageWriter();
265 setMessageWriter(msg);
266
267 uploadPack = spawn(getOptionUploadPack());
268
269 final InputStream upErr = uploadPack.getErrorStream();
270 errorReaderThread = new StreamCopyThread(upErr, msg.getRawStream());
271 errorReaderThread.start();
272
273 InputStream upIn = uploadPack.getInputStream();
274 OutputStream upOut = uploadPack.getOutputStream();
275
276 upIn = new BufferedInputStream(upIn);
277 upOut = new BufferedOutputStream(upOut);
278
279 init(upIn, upOut);
280 readAdvertisedRefs();
281 }
282
283 @Override
284 public void close() {
285 super.close();
286
287 if (uploadPack != null) {
288 try {
289 uploadPack.waitFor();
290 } catch (InterruptedException ie) {
291
292 } finally {
293 uploadPack = null;
294 }
295 }
296
297 if (errorReaderThread != null) {
298 try {
299 errorReaderThread.join();
300 } catch (InterruptedException e) {
301
302 } finally {
303 errorReaderThread = null;
304 }
305 }
306 }
307 }
308
309 class ForkLocalPushConnection extends BasePackPushConnection {
310 private Process receivePack;
311
312 private Thread errorReaderThread;
313
314 ForkLocalPushConnection() throws TransportException {
315 super(TransportLocal.this);
316
317 final MessageWriter msg = new MessageWriter();
318 setMessageWriter(msg);
319
320 receivePack = spawn(getOptionReceivePack());
321
322 final InputStream rpErr = receivePack.getErrorStream();
323 errorReaderThread = new StreamCopyThread(rpErr, msg.getRawStream());
324 errorReaderThread.start();
325
326 InputStream rpIn = receivePack.getInputStream();
327 OutputStream rpOut = receivePack.getOutputStream();
328
329 rpIn = new BufferedInputStream(rpIn);
330 rpOut = new BufferedOutputStream(rpOut);
331
332 init(rpIn, rpOut);
333 readAdvertisedRefs();
334 }
335
336 @Override
337 public void close() {
338 super.close();
339
340 if (receivePack != null) {
341 try {
342 receivePack.waitFor();
343 } catch (InterruptedException ie) {
344
345 } finally {
346 receivePack = null;
347 }
348 }
349
350 if (errorReaderThread != null) {
351 try {
352 errorReaderThread.join();
353 } catch (InterruptedException e) {
354
355 } finally {
356 errorReaderThread = null;
357 }
358 }
359 }
360 }
361 }