2 * Copyright (C) 2008 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.jgit
.transport
;
19 import java
.net
.URISyntaxException
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Collection
;
22 import java
.util
.Collections
;
23 import java
.util
.List
;
25 import org
.spearce
.jgit
.errors
.NotSupportedException
;
26 import org
.spearce
.jgit
.errors
.TransportException
;
27 import org
.spearce
.jgit
.lib
.NullProgressMonitor
;
28 import org
.spearce
.jgit
.lib
.ProgressMonitor
;
29 import org
.spearce
.jgit
.lib
.Repository
;
32 * Connects two Git repositories together and copies objects between them.
34 * A transport can be used for either fetching (copying objects into the
35 * caller's repository from the remote repository) or pushing (copying objects
36 * into the remote repository from the caller's repository). Each transport
37 * implementation is responsible for the details associated with establishing
38 * the network connection(s) necessary for the copy, as well as actually
39 * shuffling data back and forth.
41 * Transport instances and the connections they create are not thread-safe.
42 * Callers must ensure a transport is accessed by only one thread at a time.
44 public abstract class Transport
{
46 * Open a new transport instance to connect two repositories.
49 * existing local repository.
51 * location of the remote repository.
52 * @return the new transport instance. Never null.
53 * @throws URISyntaxException
54 * the location is not a remote defined in the configuration
55 * file and is not a well-formed URL.
56 * @throws NotSupportedException
57 * the protocol specified is not supported.
59 public static Transport
open(final Repository local
, final String remote
)
60 throws NotSupportedException
, URISyntaxException
{
61 final RemoteConfig cfg
= new RemoteConfig(local
.getConfig(), remote
);
62 final List
<URIish
> uris
= cfg
.getURIs();
64 return open(local
, new URIish(remote
));
65 return open(local
, cfg
);
69 * Open a new transport instance to connect two repositories.
72 * existing local repository.
74 * configuration describing how to connect to the remote
76 * @return the new transport instance. Never null.
77 * @throws NotSupportedException
78 * the protocol specified is not supported.
80 public static Transport
open(final Repository local
, final RemoteConfig cfg
)
81 throws NotSupportedException
{
82 final Transport tn
= open(local
, cfg
.getURIs().get(0));
83 tn
.setOptionUploadPack(cfg
.getUploadPack());
84 tn
.fetch
= cfg
.getFetchRefSpecs();
85 tn
.tagopt
= cfg
.getTagOpt();
90 * Open a new transport instance to connect two repositories.
93 * existing local repository.
95 * location of the remote repository.
96 * @return the new transport instance. Never null.
97 * @throws NotSupportedException
98 * the protocol specified is not supported.
100 public static Transport
open(final Repository local
, final URIish remote
)
101 throws NotSupportedException
{
102 if (TransportGitSsh
.canHandle(remote
))
103 return new TransportGitSsh(local
, remote
);
105 else if (TransportHttp
.canHandle(remote
))
106 return new TransportHttp(local
, remote
);
108 else if (TransportSftp
.canHandle(remote
))
109 return new TransportSftp(local
, remote
);
111 else if (TransportGitAnon
.canHandle(remote
))
112 return new TransportGitAnon(local
, remote
);
114 else if (TransportBundle
.canHandle(remote
))
115 return new TransportBundle(local
, remote
);
117 else if (TransportLocal
.canHandle(remote
))
118 return new TransportLocal(local
, remote
);
120 throw new NotSupportedException("URI not supported: " + remote
);
123 /** The repository this transport fetches into, or pushes out of. */
124 protected final Repository local
;
126 /** The URI used to create this transport. */
127 protected final URIish uri
;
129 /** Name of the upload pack program, if it must be executed. */
130 private String optionUploadPack
= RemoteConfig
.DEFAULT_UPLOAD_PACK
;
132 /** Specifications to apply during fetch. */
133 private List
<RefSpec
> fetch
= Collections
.<RefSpec
> emptyList();
136 * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
138 * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
139 * tags during one-shot fetches used for later merges. This prevents
140 * dragging down tags from repositories that we do not have established
141 * tracking branches for. If we do not track the source repository, we most
142 * likely do not care about any tags it publishes.
144 private TagOpt tagopt
= TagOpt
.NO_TAGS
;
147 * Create a new transport instance.
150 * the repository this instance will fetch into, or push out of.
151 * This must be the repository passed to
152 * {@link #open(Repository, URIish)}.
154 * the URI used to access the remote repository. This must be the
155 * URI passed to {@link #open(Repository, URIish)}.
157 protected Transport(final Repository local
, final URIish uri
) {
163 * Get the URI this transport connects to.
165 * Each transport instance connects to at most one URI at any point in time.
167 * @return the URI describing the location of the remote repository.
169 public URIish
getURI() {
174 * Get the name of the remote executable providing upload-pack service.
176 * @return typically "git-upload-pack".
178 public String
getOptionUploadPack() {
179 return optionUploadPack
;
183 * Set the name of the remote executable providing upload-pack services.
186 * name of the executable.
188 public void setOptionUploadPack(final String where
) {
189 if (where
!= null && where
.length() > 0)
190 optionUploadPack
= where
;
192 optionUploadPack
= RemoteConfig
.DEFAULT_UPLOAD_PACK
;
196 * Get the description of how annotated tags should be treated during fetch.
198 * @return option indicating the behavior of annotated tags in fetch.
200 public TagOpt
getTagOpt() {
205 * Set the description of how annotated tags should be treated on fetch.
208 * method to use when handling annotated tags.
210 public void setTagOpt(final TagOpt option
) {
211 tagopt
= option
!= null ? option
: TagOpt
.AUTO_FOLLOW
;
215 * Fetch objects and refs from the remote repository to the local one.
217 * This is a utility function providing standard fetch behavior. Local
218 * tracking refs associated with the remote repository are automatically
219 * updated if this transport was created from a {@link RemoteConfig} with
220 * fetch RefSpecs defined.
223 * progress monitor to inform the user about our processing
224 * activity. Must not be null. Use {@link NullProgressMonitor} if
225 * progress updates are not interesting or necessary.
227 * specification of refs to fetch locally. May be null or the
228 * empty collection to use the specifications from the
230 * @return information describing the tracking refs updated.
231 * @throws NotSupportedException
232 * this transport implementation does not support fetching
234 * @throws TransportException
235 * the remote connection could not be established or object
236 * copying (if necessary) failed.
238 public FetchResult
fetch(final ProgressMonitor monitor
,
239 Collection
<RefSpec
> toFetch
) throws NotSupportedException
,
241 if (toFetch
== null || toFetch
.isEmpty()) {
242 // If the caller did not ask for anything use the defaults.
245 throw new TransportException("Nothing to fetch.");
247 } else if (!fetch
.isEmpty()) {
248 // If the caller asked for something specific without giving
249 // us the local tracking branch see if we can update any of
250 // the local tracking branches without incurring additional
251 // object transfer overheads.
253 final Collection
<RefSpec
> tmp
= new ArrayList
<RefSpec
>(toFetch
);
254 for (final RefSpec requested
: toFetch
) {
255 final String reqSrc
= requested
.getSource();
256 for (final RefSpec configured
: fetch
) {
257 final String cfgSrc
= configured
.getSource();
258 final String cfgDst
= configured
.getDestination();
259 if (cfgSrc
.equals(reqSrc
) && cfgDst
!= null) {
268 final FetchResult result
= new FetchResult();
269 new FetchProcess(this, toFetch
).execute(monitor
, result
);
274 * Begins a new connection for fetching from the remote repository.
276 * @return a fresh connection to fetch from the remote repository.
277 * @throws NotSupportedException
278 * the implementation does not support fetching.
279 * @throws TransportException
280 * the remote connection could not be established.
282 public abstract FetchConnection
openFetch() throws NotSupportedException
,
286 * Begins a new connection for pushing into the remote repository.
288 * @return a fresh connection to push into the remote repository.
289 * @throws NotSupportedException
290 * the implementation does not support pushing.
292 public final PushConnection
openPush() throws NotSupportedException
293 /* TransportException */{
294 throw new NotSupportedException("No push support.");