]> source.dussan.org Git - jgit.git/commitdiff
Extract classes for transport within a JGit process 33/42933/1
authorDave Borowitz <dborowitz@google.com>
Fri, 27 Feb 2015 23:04:35 +0000 (15:04 -0800)
committerDave Borowitz <dborowitz@google.com>
Fri, 27 Feb 2015 23:22:15 +0000 (15:22 -0800)
TransportLocal knows how to spin up a thread to allow two repositories
in the same process to communicate using the wire protocol. However,
it is still tied to local on-disk filesystems, and needs to be able to
fork processes if not using the default git-{upload,receive}-pack
implementation.

Extract out the connection classes so they can be used by other
transport implementations.

Change-Id: I5db59086740735508c2e70a597c2d1a89014b072

org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java
new file mode 100644 (file)
index 0000000..7fc4048
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.transport;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
+import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.transport.resolver.UploadPackFactory;
+
+class InternalFetchConnection<C> extends BasePackFetchConnection {
+       private Thread worker;
+
+       public InternalFetchConnection(PackTransport transport,
+                       final UploadPackFactory<C> uploadPackFactory,
+                       final C req, final Repository remote) throws TransportException {
+               super(transport);
+
+               final PipedInputStream in_r;
+               final PipedOutputStream in_w;
+
+               final PipedInputStream out_r;
+               final PipedOutputStream out_w;
+               try {
+                       in_r = new PipedInputStream();
+                       in_w = new PipedOutputStream(in_r);
+
+                       out_r = new PipedInputStream() {
+                               // The client (BasePackFetchConnection) can write
+                               // a huge burst before it reads again. We need to
+                               // force the buffer to be big enough, otherwise it
+                               // will deadlock both threads.
+                               {
+                                       buffer = new byte[MIN_CLIENT_BUFFER];
+                               }
+                       };
+                       out_w = new PipedOutputStream(out_r);
+               } catch (IOException err) {
+                       remote.close();
+                       throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
+               }
+
+               worker = new Thread("JGit-Upload-Pack") { //$NON-NLS-1$
+                       public void run() {
+                               try {
+                                       final UploadPack rp = uploadPackFactory.create(req, remote);
+                                       rp.upload(out_r, in_w, null);
+                               } catch (ServiceNotEnabledException e) {
+                                       // Ignored. Client cannot use this repository.
+                               } catch (ServiceNotAuthorizedException e) {
+                                       // Ignored. Client cannot use this repository.
+                               } catch (IOException err) {
+                                       // Client side of the pipes should report the problem.
+                                       err.printStackTrace();
+                               } catch (RuntimeException err) {
+                                       // Client side will notice we went away, and report.
+                                       err.printStackTrace();
+                               } finally {
+                                       try {
+                                               out_r.close();
+                                       } catch (IOException e2) {
+                                               // Ignore close failure, we probably crashed above.
+                                       }
+
+                                       try {
+                                               in_w.close();
+                                       } catch (IOException e2) {
+                                               // Ignore close failure, we probably crashed above.
+                                       }
+
+                                       remote.close();
+                               }
+                       }
+               };
+               worker.start();
+
+               init(in_r, out_w);
+               readAdvertisedRefs();
+       }
+
+       @Override
+       public void close() {
+               super.close();
+
+               try {
+                       if (worker != null) {
+                               worker.join();
+                       }
+               } catch (InterruptedException ie) {
+                       // Stop waiting and return anyway.
+               } finally {
+                       worker = null;
+               }
+       }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java
new file mode 100644 (file)
index 0000000..ab76e0f
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.transport;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
+import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
+import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+
+class InternalPushConnection<C> extends BasePackPushConnection {
+       private Thread worker;
+
+       public InternalPushConnection(PackTransport transport,
+                       final ReceivePackFactory<C> receivePackFactory,
+                       final C req, final Repository remote) throws TransportException {
+               super(transport);
+
+               final PipedInputStream in_r;
+               final PipedOutputStream in_w;
+
+               final PipedInputStream out_r;
+               final PipedOutputStream out_w;
+               try {
+                       in_r = new PipedInputStream();
+                       in_w = new PipedOutputStream(in_r);
+
+                       out_r = new PipedInputStream();
+                       out_w = new PipedOutputStream(out_r);
+               } catch (IOException err) {
+                       remote.close();
+                       throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
+               }
+
+               worker = new Thread("JGit-Receive-Pack") { //$NON-NLS-1$
+                       public void run() {
+                               try {
+                                       final ReceivePack rp = receivePackFactory.create(req, remote);
+                                       rp.receive(out_r, in_w, System.err);
+                               } catch (ServiceNotEnabledException e) {
+                                       // Ignored. Client cannot use this repository.
+                               } catch (ServiceNotAuthorizedException e) {
+                                       // Ignored. Client cannot use this repository.
+                               } catch (IOException err) {
+                                       // Client side of the pipes should report the problem.
+                               } catch (RuntimeException err) {
+                                       // Clients side will notice we went away, and report.
+                               } finally {
+                                       try {
+                                               out_r.close();
+                                       } catch (IOException e2) {
+                                               // Ignore close failure, we probably crashed above.
+                                       }
+
+                                       try {
+                                               in_w.close();
+                                       } catch (IOException e2) {
+                                               // Ignore close failure, we probably crashed above.
+                                       }
+
+                                       remote.close();
+                               }
+                       }
+               };
+               worker.start();
+
+               init(in_r, out_w);
+               readAdvertisedRefs();
+       }
+
+       @Override
+       public void close() {
+               super.close();
+
+               if (worker != null) {
+                       try {
+                               worker.join();
+                       } catch (InterruptedException ie) {
+                               // Stop waiting and return anyway.
+                       } finally {
+                               worker = null;
+                       }
+               }
+       }
+}
index 81caf66491af01595f1bef7e7af26203845ef210..292ba7ed8a484345adf286f0d9469aa4aafbaf21 100644 (file)
@@ -52,8 +52,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -65,6 +63,8 @@ import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryBuilder;
 import org.eclipse.jgit.lib.RepositoryCache;
+import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
+import org.eclipse.jgit.transport.resolver.UploadPackFactory;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.io.MessageWriter;
 import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
@@ -168,21 +168,44 @@ class TransportLocal extends Transport implements PackTransport {
                return new ReceivePack(dst);
        }
 
+       private Repository openRepo() throws TransportException {
+               try {
+                       return new RepositoryBuilder().setGitDir(remoteGitDir).build();
+               } catch (IOException err) {
+                       throw new TransportException(uri, JGitText.get().notAGitDirectory);
+               }
+       }
+
        @Override
        public FetchConnection openFetch() throws TransportException {
                final String up = getOptionUploadPack();
-               if ("git-upload-pack".equals(up) || "git upload-pack".equals(up)) //$NON-NLS-1$ //$NON-NLS-2$
-                       return new InternalLocalFetchConnection();
-               return new ForkLocalFetchConnection();
+               if (!"git-upload-pack".equals(up) //$NON-NLS-1$
+                               && !"git upload-pack".equals(up)) //$NON-NLS-1$
+                       return new ForkLocalFetchConnection();
+
+               UploadPackFactory<Void> upf = new UploadPackFactory<Void>() {
+                       @Override
+                       public UploadPack create(Void req, Repository db) {
+                               return createUploadPack(db);
+                       }
+               };
+               return new InternalFetchConnection<Void>(this, upf, null, openRepo());
        }
 
        @Override
-       public PushConnection openPush() throws NotSupportedException,
-                       TransportException {
+       public PushConnection openPush() throws TransportException {
                final String rp = getOptionReceivePack();
-               if ("git-receive-pack".equals(rp) || "git receive-pack".equals(rp)) //$NON-NLS-1$ //$NON-NLS-2$
-                       return new InternalLocalPushConnection();
-               return new ForkLocalPushConnection();
+               if (!"git-receive-pack".equals(rp) //$NON-NLS-1$
+                               && !"git receive-pack".equals(rp)) //$NON-NLS-1$
+                       return new ForkLocalPushConnection();
+
+               ReceivePackFactory<Void> rpf = new ReceivePackFactory<Void>() {
+                       @Override
+                       public ReceivePack create(Void req, Repository db) {
+                               return createReceivePack(db);
+                       }
+               };
+               return new InternalPushConnection<Void>(this, rpf, null, openRepo());
        }
 
        @Override
@@ -214,93 +237,6 @@ class TransportLocal extends Transport implements PackTransport {
                }
        }
 
-       class InternalLocalFetchConnection extends BasePackFetchConnection {
-               private Thread worker;
-
-               InternalLocalFetchConnection() throws TransportException {
-                       super(TransportLocal.this);
-
-                       final Repository dst;
-                       try {
-                               dst = new RepositoryBuilder().setGitDir(remoteGitDir).build();
-                       } catch (IOException err) {
-                               throw new TransportException(uri, JGitText.get().notAGitDirectory);
-                       }
-
-                       final PipedInputStream in_r;
-                       final PipedOutputStream in_w;
-
-                       final PipedInputStream out_r;
-                       final PipedOutputStream out_w;
-                       try {
-                               in_r = new PipedInputStream();
-                               in_w = new PipedOutputStream(in_r);
-
-                               out_r = new PipedInputStream() {
-                                       // The client (BasePackFetchConnection) can write
-                                       // a huge burst before it reads again. We need to
-                                       // force the buffer to be big enough, otherwise it
-                                       // will deadlock both threads.
-                                       {
-                                               buffer = new byte[MIN_CLIENT_BUFFER];
-                                       }
-                               };
-                               out_w = new PipedOutputStream(out_r);
-                       } catch (IOException err) {
-                               dst.close();
-                               throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
-                       }
-
-                       worker = new Thread("JGit-Upload-Pack") { //$NON-NLS-1$
-                               public void run() {
-                                       try {
-                                               final UploadPack rp = createUploadPack(dst);
-                                               rp.upload(out_r, in_w, null);
-                                       } catch (IOException err) {
-                                               // Client side of the pipes should report the problem.
-                                               err.printStackTrace();
-                                       } catch (RuntimeException err) {
-                                               // Clients side will notice we went away, and report.
-                                               err.printStackTrace();
-                                       } finally {
-                                               try {
-                                                       out_r.close();
-                                               } catch (IOException e2) {
-                                                       // Ignore close failure, we probably crashed above.
-                                               }
-
-                                               try {
-                                                       in_w.close();
-                                               } catch (IOException e2) {
-                                                       // Ignore close failure, we probably crashed above.
-                                               }
-
-                                               dst.close();
-                                       }
-                               }
-                       };
-                       worker.start();
-
-                       init(in_r, out_w);
-                       readAdvertisedRefs();
-               }
-
-               @Override
-               public void close() {
-                       super.close();
-
-                       if (worker != null) {
-                               try {
-                                       worker.join();
-                               } catch (InterruptedException ie) {
-                                       // Stop waiting and return anyway.
-                               } finally {
-                                       worker = null;
-                               }
-                       }
-               }
-       }
-
        class ForkLocalFetchConnection extends BasePackFetchConnection {
                private Process uploadPack;
 
@@ -354,83 +290,6 @@ class TransportLocal extends Transport implements PackTransport {
                }
        }
 
-       class InternalLocalPushConnection extends BasePackPushConnection {
-               private Thread worker;
-
-               InternalLocalPushConnection() throws TransportException {
-                       super(TransportLocal.this);
-
-                       final Repository dst;
-                       try {
-                               dst = new RepositoryBuilder().setGitDir(remoteGitDir).build();
-                       } catch (IOException err) {
-                               throw new TransportException(uri, JGitText.get().notAGitDirectory);
-                       }
-
-                       final PipedInputStream in_r;
-                       final PipedOutputStream in_w;
-
-                       final PipedInputStream out_r;
-                       final PipedOutputStream out_w;
-                       try {
-                               in_r = new PipedInputStream();
-                               in_w = new PipedOutputStream(in_r);
-
-                               out_r = new PipedInputStream();
-                               out_w = new PipedOutputStream(out_r);
-                       } catch (IOException err) {
-                               dst.close();
-                               throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
-                       }
-
-                       worker = new Thread("JGit-Receive-Pack") { //$NON-NLS-1$
-                               public void run() {
-                                       try {
-                                               final ReceivePack rp = createReceivePack(dst);
-                                               rp.receive(out_r, in_w, System.err);
-                                       } catch (IOException err) {
-                                               // Client side of the pipes should report the problem.
-                                       } catch (RuntimeException err) {
-                                               // Clients side will notice we went away, and report.
-                                       } finally {
-                                               try {
-                                                       out_r.close();
-                                               } catch (IOException e2) {
-                                                       // Ignore close failure, we probably crashed above.
-                                               }
-
-                                               try {
-                                                       in_w.close();
-                                               } catch (IOException e2) {
-                                                       // Ignore close failure, we probably crashed above.
-                                               }
-
-                                               dst.close();
-                                       }
-                               }
-                       };
-                       worker.start();
-
-                       init(in_r, out_w);
-                       readAdvertisedRefs();
-               }
-
-               @Override
-               public void close() {
-                       super.close();
-
-                       if (worker != null) {
-                               try {
-                                       worker.join();
-                               } catch (InterruptedException ie) {
-                                       // Stop waiting and return anyway.
-                               } finally {
-                                       worker = null;
-                               }
-                       }
-               }
-       }
-
        class ForkLocalPushConnection extends BasePackPushConnection {
                private Process receivePack;