You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Transport.java 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /*
  2. * Copyright (C) 2008-2009, Google Inc.
  3. * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  4. * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  5. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  6. * and other copyright owners as documented in the project's IP log.
  7. *
  8. * This program and the accompanying materials are made available
  9. * under the terms of the Eclipse Distribution License v1.0 which
  10. * accompanies this distribution, is reproduced below, and is
  11. * available at http://www.eclipse.org/org/documents/edl-v10.php
  12. *
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or
  16. * without modification, are permitted provided that the following
  17. * conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. *
  22. * - Redistributions in binary form must reproduce the above
  23. * copyright notice, this list of conditions and the following
  24. * disclaimer in the documentation and/or other materials provided
  25. * with the distribution.
  26. *
  27. * - Neither the name of the Eclipse Foundation, Inc. nor the
  28. * names of its contributors may be used to endorse or promote
  29. * products derived from this software without specific prior
  30. * written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  33. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  34. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  35. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  37. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  39. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  40. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  41. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  42. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  43. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  44. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. */
  46. package org.eclipse.jgit.transport;
  47. import static org.eclipse.jgit.lib.RefDatabase.ALL;
  48. import java.io.BufferedReader;
  49. import java.io.IOException;
  50. import java.io.InputStream;
  51. import java.io.InputStreamReader;
  52. import java.io.OutputStream;
  53. import java.lang.ref.WeakReference;
  54. import java.lang.reflect.Field;
  55. import java.lang.reflect.Modifier;
  56. import java.net.URISyntaxException;
  57. import java.net.URL;
  58. import java.text.MessageFormat;
  59. import java.util.ArrayList;
  60. import java.util.Collection;
  61. import java.util.Collections;
  62. import java.util.Enumeration;
  63. import java.util.HashSet;
  64. import java.util.LinkedList;
  65. import java.util.List;
  66. import java.util.Map;
  67. import java.util.Vector;
  68. import java.util.concurrent.CopyOnWriteArrayList;
  69. import org.eclipse.jgit.errors.NotSupportedException;
  70. import org.eclipse.jgit.errors.TransportException;
  71. import org.eclipse.jgit.internal.JGitText;
  72. import org.eclipse.jgit.lib.Constants;
  73. import org.eclipse.jgit.lib.NullProgressMonitor;
  74. import org.eclipse.jgit.lib.ObjectChecker;
  75. import org.eclipse.jgit.lib.ProgressMonitor;
  76. import org.eclipse.jgit.lib.Ref;
  77. import org.eclipse.jgit.lib.Repository;
  78. import org.eclipse.jgit.storage.pack.PackConfig;
  79. /**
  80. * Connects two Git repositories together and copies objects between them.
  81. * <p>
  82. * A transport can be used for either fetching (copying objects into the
  83. * caller's repository from the remote repository) or pushing (copying objects
  84. * into the remote repository from the caller's repository). Each transport
  85. * implementation is responsible for the details associated with establishing
  86. * the network connection(s) necessary for the copy, as well as actually
  87. * shuffling data back and forth.
  88. * <p>
  89. * Transport instances and the connections they create are not thread-safe.
  90. * Callers must ensure a transport is accessed by only one thread at a time.
  91. */
  92. public abstract class Transport {
  93. /** Type of operation a Transport is being opened for. */
  94. public enum Operation {
  95. /** Transport is to fetch objects locally. */
  96. FETCH,
  97. /** Transport is to push objects remotely. */
  98. PUSH;
  99. }
  100. private static final List<WeakReference<TransportProtocol>> protocols =
  101. new CopyOnWriteArrayList<WeakReference<TransportProtocol>>();
  102. static {
  103. // Registration goes backwards in order of priority.
  104. register(TransportLocal.PROTO_LOCAL);
  105. register(TransportBundleFile.PROTO_BUNDLE);
  106. register(TransportAmazonS3.PROTO_S3);
  107. register(TransportGitAnon.PROTO_GIT);
  108. register(TransportSftp.PROTO_SFTP);
  109. register(TransportHttp.PROTO_FTP);
  110. register(TransportHttp.PROTO_HTTP);
  111. register(TransportGitSsh.PROTO_SSH);
  112. registerByService();
  113. }
  114. private static void registerByService() {
  115. ClassLoader ldr = Thread.currentThread().getContextClassLoader();
  116. if (ldr == null)
  117. ldr = Transport.class.getClassLoader();
  118. Enumeration<URL> catalogs = catalogs(ldr);
  119. while (catalogs.hasMoreElements())
  120. scan(ldr, catalogs.nextElement());
  121. }
  122. private static Enumeration<URL> catalogs(ClassLoader ldr) {
  123. try {
  124. String prefix = "META-INF/services/"; //$NON-NLS-1$
  125. String name = prefix + Transport.class.getName();
  126. return ldr.getResources(name);
  127. } catch (IOException err) {
  128. return new Vector<URL>().elements();
  129. }
  130. }
  131. private static void scan(ClassLoader ldr, URL url) {
  132. BufferedReader br;
  133. try {
  134. InputStream urlIn = url.openStream();
  135. br = new BufferedReader(new InputStreamReader(urlIn, "UTF-8")); //$NON-NLS-1$
  136. } catch (IOException err) {
  137. // If we cannot read from the service list, go to the next.
  138. //
  139. return;
  140. }
  141. try {
  142. String line;
  143. while ((line = br.readLine()) != null) {
  144. line = line.trim();
  145. if (line.length() == 0)
  146. continue;
  147. int comment = line.indexOf('#');
  148. if (comment == 0)
  149. continue;
  150. if (comment != -1)
  151. line = line.substring(0, comment).trim();
  152. load(ldr, line);
  153. }
  154. } catch (IOException err) {
  155. // If we failed during a read, ignore the error.
  156. //
  157. } finally {
  158. try {
  159. br.close();
  160. } catch (IOException e) {
  161. // Ignore the close error; we are only reading.
  162. }
  163. }
  164. }
  165. private static void load(ClassLoader ldr, String cn) {
  166. Class<?> clazz;
  167. try {
  168. clazz = Class.forName(cn, false, ldr);
  169. } catch (ClassNotFoundException notBuiltin) {
  170. // Doesn't exist, even though the service entry is present.
  171. //
  172. return;
  173. }
  174. for (Field f : clazz.getDeclaredFields()) {
  175. if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC
  176. && TransportProtocol.class.isAssignableFrom(f.getType())) {
  177. TransportProtocol proto;
  178. try {
  179. proto = (TransportProtocol) f.get(null);
  180. } catch (IllegalArgumentException e) {
  181. // If we cannot access the field, don't.
  182. continue;
  183. } catch (IllegalAccessException e) {
  184. // If we cannot access the field, don't.
  185. continue;
  186. }
  187. if (proto != null)
  188. register(proto);
  189. }
  190. }
  191. }
  192. /**
  193. * Register a TransportProtocol instance for use during open.
  194. * <p>
  195. * Protocol definitions are held by WeakReference, allowing them to be
  196. * garbage collected when the calling application drops all strongly held
  197. * references to the TransportProtocol. Therefore applications should use a
  198. * singleton pattern as described in {@link TransportProtocol}'s class
  199. * documentation to ensure their protocol does not get disabled by garbage
  200. * collection earlier than expected.
  201. * <p>
  202. * The new protocol is registered in front of all earlier protocols, giving
  203. * it higher priority than the built-in protocol definitions.
  204. *
  205. * @param proto
  206. * the protocol definition. Must not be null.
  207. */
  208. public static void register(TransportProtocol proto) {
  209. protocols.add(0, new WeakReference<TransportProtocol>(proto));
  210. }
  211. /**
  212. * Unregister a TransportProtocol instance.
  213. * <p>
  214. * Unregistering a protocol usually isn't necessary, as protocols are held
  215. * by weak references and will automatically clear when they are garbage
  216. * collected by the JVM. Matching is handled by reference equality, so the
  217. * exact reference given to {@link #register(TransportProtocol)} must be
  218. * used.
  219. *
  220. * @param proto
  221. * the exact object previously given to register.
  222. */
  223. public static void unregister(TransportProtocol proto) {
  224. for (WeakReference<TransportProtocol> ref : protocols) {
  225. TransportProtocol refProto = ref.get();
  226. if (refProto == null || refProto == proto)
  227. protocols.remove(ref);
  228. }
  229. }
  230. /**
  231. * Obtain a copy of the registered protocols.
  232. *
  233. * @return an immutable copy of the currently registered protocols.
  234. */
  235. public static List<TransportProtocol> getTransportProtocols() {
  236. int cnt = protocols.size();
  237. List<TransportProtocol> res = new ArrayList<TransportProtocol>(cnt);
  238. for (WeakReference<TransportProtocol> ref : protocols) {
  239. TransportProtocol proto = ref.get();
  240. if (proto != null)
  241. res.add(proto);
  242. else
  243. protocols.remove(ref);
  244. }
  245. return Collections.unmodifiableList(res);
  246. }
  247. /**
  248. * Open a new transport instance to connect two repositories.
  249. * <p>
  250. * This method assumes {@link Operation#FETCH}.
  251. *
  252. * @param local
  253. * existing local repository.
  254. * @param remote
  255. * location of the remote repository - may be URI or remote
  256. * configuration name.
  257. * @return the new transport instance. Never null. In case of multiple URIs
  258. * in remote configuration, only the first is chosen.
  259. * @throws URISyntaxException
  260. * the location is not a remote defined in the configuration
  261. * file and is not a well-formed URL.
  262. * @throws NotSupportedException
  263. * the protocol specified is not supported.
  264. * @throws TransportException
  265. * the transport cannot open this URI.
  266. */
  267. public static Transport open(final Repository local, final String remote)
  268. throws NotSupportedException, URISyntaxException,
  269. TransportException {
  270. return open(local, remote, Operation.FETCH);
  271. }
  272. /**
  273. * Open a new transport instance to connect two repositories.
  274. *
  275. * @param local
  276. * existing local repository.
  277. * @param remote
  278. * location of the remote repository - may be URI or remote
  279. * configuration name.
  280. * @param op
  281. * planned use of the returned Transport; the URI may differ
  282. * based on the type of connection desired.
  283. * @return the new transport instance. Never null. In case of multiple URIs
  284. * in remote configuration, only the first is chosen.
  285. * @throws URISyntaxException
  286. * the location is not a remote defined in the configuration
  287. * file and is not a well-formed URL.
  288. * @throws NotSupportedException
  289. * the protocol specified is not supported.
  290. * @throws TransportException
  291. * the transport cannot open this URI.
  292. */
  293. public static Transport open(final Repository local, final String remote,
  294. final Operation op) throws NotSupportedException,
  295. URISyntaxException, TransportException {
  296. if (local != null) {
  297. final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  298. if (doesNotExist(cfg))
  299. return open(local, new URIish(remote), null);
  300. return open(local, cfg, op);
  301. } else
  302. return open(new URIish(remote));
  303. }
  304. /**
  305. * Open new transport instances to connect two repositories.
  306. * <p>
  307. * This method assumes {@link Operation#FETCH}.
  308. *
  309. * @param local
  310. * existing local repository.
  311. * @param remote
  312. * location of the remote repository - may be URI or remote
  313. * configuration name.
  314. * @return the list of new transport instances for every URI in remote
  315. * configuration.
  316. * @throws URISyntaxException
  317. * the location is not a remote defined in the configuration
  318. * file and is not a well-formed URL.
  319. * @throws NotSupportedException
  320. * the protocol specified is not supported.
  321. * @throws TransportException
  322. * the transport cannot open this URI.
  323. */
  324. public static List<Transport> openAll(final Repository local,
  325. final String remote) throws NotSupportedException,
  326. URISyntaxException, TransportException {
  327. return openAll(local, remote, Operation.FETCH);
  328. }
  329. /**
  330. * Open new transport instances to connect two repositories.
  331. *
  332. * @param local
  333. * existing local repository.
  334. * @param remote
  335. * location of the remote repository - may be URI or remote
  336. * configuration name.
  337. * @param op
  338. * planned use of the returned Transport; the URI may differ
  339. * based on the type of connection desired.
  340. * @return the list of new transport instances for every URI in remote
  341. * configuration.
  342. * @throws URISyntaxException
  343. * the location is not a remote defined in the configuration
  344. * file and is not a well-formed URL.
  345. * @throws NotSupportedException
  346. * the protocol specified is not supported.
  347. * @throws TransportException
  348. * the transport cannot open this URI.
  349. */
  350. public static List<Transport> openAll(final Repository local,
  351. final String remote, final Operation op)
  352. throws NotSupportedException, URISyntaxException,
  353. TransportException {
  354. final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  355. if (doesNotExist(cfg)) {
  356. final ArrayList<Transport> transports = new ArrayList<Transport>(1);
  357. transports.add(open(local, new URIish(remote), null));
  358. return transports;
  359. }
  360. return openAll(local, cfg, op);
  361. }
  362. /**
  363. * Open a new transport instance to connect two repositories.
  364. * <p>
  365. * This method assumes {@link Operation#FETCH}.
  366. *
  367. * @param local
  368. * existing local repository.
  369. * @param cfg
  370. * configuration describing how to connect to the remote
  371. * repository.
  372. * @return the new transport instance. Never null. In case of multiple URIs
  373. * in remote configuration, only the first is chosen.
  374. * @throws NotSupportedException
  375. * the protocol specified is not supported.
  376. * @throws TransportException
  377. * the transport cannot open this URI.
  378. * @throws IllegalArgumentException
  379. * if provided remote configuration doesn't have any URI
  380. * associated.
  381. */
  382. public static Transport open(final Repository local, final RemoteConfig cfg)
  383. throws NotSupportedException, TransportException {
  384. return open(local, cfg, Operation.FETCH);
  385. }
  386. /**
  387. * Open a new transport instance to connect two repositories.
  388. *
  389. * @param local
  390. * existing local repository.
  391. * @param cfg
  392. * configuration describing how to connect to the remote
  393. * repository.
  394. * @param op
  395. * planned use of the returned Transport; the URI may differ
  396. * based on the type of connection desired.
  397. * @return the new transport instance. Never null. In case of multiple URIs
  398. * in remote configuration, only the first is chosen.
  399. * @throws NotSupportedException
  400. * the protocol specified is not supported.
  401. * @throws TransportException
  402. * the transport cannot open this URI.
  403. * @throws IllegalArgumentException
  404. * if provided remote configuration doesn't have any URI
  405. * associated.
  406. */
  407. public static Transport open(final Repository local,
  408. final RemoteConfig cfg, final Operation op)
  409. throws NotSupportedException, TransportException {
  410. final List<URIish> uris = getURIs(cfg, op);
  411. if (uris.isEmpty())
  412. throw new IllegalArgumentException(MessageFormat.format(
  413. JGitText.get().remoteConfigHasNoURIAssociated, cfg.getName()));
  414. final Transport tn = open(local, uris.get(0), cfg.getName());
  415. tn.applyConfig(cfg);
  416. return tn;
  417. }
  418. /**
  419. * Open new transport instances to connect two repositories.
  420. * <p>
  421. * This method assumes {@link Operation#FETCH}.
  422. *
  423. * @param local
  424. * existing local repository.
  425. * @param cfg
  426. * configuration describing how to connect to the remote
  427. * repository.
  428. * @return the list of new transport instances for every URI in remote
  429. * configuration.
  430. * @throws NotSupportedException
  431. * the protocol specified is not supported.
  432. * @throws TransportException
  433. * the transport cannot open this URI.
  434. */
  435. public static List<Transport> openAll(final Repository local,
  436. final RemoteConfig cfg) throws NotSupportedException,
  437. TransportException {
  438. return openAll(local, cfg, Operation.FETCH);
  439. }
  440. /**
  441. * Open new transport instances to connect two repositories.
  442. *
  443. * @param local
  444. * existing local repository.
  445. * @param cfg
  446. * configuration describing how to connect to the remote
  447. * repository.
  448. * @param op
  449. * planned use of the returned Transport; the URI may differ
  450. * based on the type of connection desired.
  451. * @return the list of new transport instances for every URI in remote
  452. * configuration.
  453. * @throws NotSupportedException
  454. * the protocol specified is not supported.
  455. * @throws TransportException
  456. * the transport cannot open this URI.
  457. */
  458. public static List<Transport> openAll(final Repository local,
  459. final RemoteConfig cfg, final Operation op)
  460. throws NotSupportedException, TransportException {
  461. final List<URIish> uris = getURIs(cfg, op);
  462. final List<Transport> transports = new ArrayList<Transport>(uris.size());
  463. for (final URIish uri : uris) {
  464. final Transport tn = open(local, uri, cfg.getName());
  465. tn.applyConfig(cfg);
  466. transports.add(tn);
  467. }
  468. return transports;
  469. }
  470. private static List<URIish> getURIs(final RemoteConfig cfg,
  471. final Operation op) {
  472. switch (op) {
  473. case FETCH:
  474. return cfg.getURIs();
  475. case PUSH: {
  476. List<URIish> uris = cfg.getPushURIs();
  477. if (uris.isEmpty())
  478. uris = cfg.getURIs();
  479. return uris;
  480. }
  481. default:
  482. throw new IllegalArgumentException(op.toString());
  483. }
  484. }
  485. private static boolean doesNotExist(final RemoteConfig cfg) {
  486. return cfg.getURIs().isEmpty() && cfg.getPushURIs().isEmpty();
  487. }
  488. /**
  489. * Open a new transport instance to connect two repositories.
  490. *
  491. * @param local
  492. * existing local repository.
  493. * @param uri
  494. * location of the remote repository.
  495. * @return the new transport instance. Never null.
  496. * @throws NotSupportedException
  497. * the protocol specified is not supported.
  498. * @throws TransportException
  499. * the transport cannot open this URI.
  500. */
  501. public static Transport open(final Repository local, final URIish uri)
  502. throws NotSupportedException, TransportException {
  503. return open(local, uri, null);
  504. }
  505. /**
  506. * Open a new transport instance to connect two repositories.
  507. *
  508. * @param local
  509. * existing local repository.
  510. * @param uri
  511. * location of the remote repository.
  512. * @param remoteName
  513. * name of the remote, if the remote as configured in
  514. * {@code local}; otherwise null.
  515. * @return the new transport instance. Never null.
  516. * @throws NotSupportedException
  517. * the protocol specified is not supported.
  518. * @throws TransportException
  519. * the transport cannot open this URI.
  520. */
  521. public static Transport open(Repository local, URIish uri, String remoteName)
  522. throws NotSupportedException, TransportException {
  523. for (WeakReference<TransportProtocol> ref : protocols) {
  524. TransportProtocol proto = ref.get();
  525. if (proto == null) {
  526. protocols.remove(ref);
  527. continue;
  528. }
  529. if (proto.canHandle(uri, local, remoteName))
  530. return proto.open(uri, local, remoteName);
  531. }
  532. throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  533. }
  534. /**
  535. * Open a new transport with no local repository.
  536. * <p>
  537. * Note that the resulting transport instance can not be used for fetching
  538. * or pushing, but only for reading remote refs.
  539. *
  540. * @param uri
  541. * @return new Transport instance
  542. * @throws NotSupportedException
  543. * @throws TransportException
  544. */
  545. public static Transport open(URIish uri) throws NotSupportedException, TransportException {
  546. for (WeakReference<TransportProtocol> ref : protocols) {
  547. TransportProtocol proto = ref.get();
  548. if (proto == null) {
  549. protocols.remove(ref);
  550. continue;
  551. }
  552. if (proto.canHandle(uri, null, null))
  553. return proto.open(uri);
  554. }
  555. throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  556. }
  557. /**
  558. * Convert push remote refs update specification from {@link RefSpec} form
  559. * to {@link RemoteRefUpdate}. Conversion expands wildcards by matching
  560. * source part to local refs. expectedOldObjectId in RemoteRefUpdate is
  561. * always set as null. Tracking branch is configured if RefSpec destination
  562. * matches source of any fetch ref spec for this transport remote
  563. * configuration.
  564. *
  565. * @param db
  566. * local database.
  567. * @param specs
  568. * collection of RefSpec to convert.
  569. * @param fetchSpecs
  570. * fetch specifications used for finding localtracking refs. May
  571. * be null or empty collection.
  572. * @return collection of set up {@link RemoteRefUpdate}.
  573. * @throws IOException
  574. * when problem occurred during conversion or specification set
  575. * up: most probably, missing objects or refs.
  576. */
  577. public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  578. final Repository db, final Collection<RefSpec> specs,
  579. Collection<RefSpec> fetchSpecs) throws IOException {
  580. if (fetchSpecs == null)
  581. fetchSpecs = Collections.emptyList();
  582. final List<RemoteRefUpdate> result = new LinkedList<RemoteRefUpdate>();
  583. final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);
  584. for (final RefSpec spec : procRefs) {
  585. String srcSpec = spec.getSource();
  586. final Ref srcRef = db.getRef(srcSpec);
  587. if (srcRef != null)
  588. srcSpec = srcRef.getName();
  589. String destSpec = spec.getDestination();
  590. if (destSpec == null) {
  591. // No destination (no-colon in ref-spec), DWIMery assumes src
  592. //
  593. destSpec = srcSpec;
  594. }
  595. if (srcRef != null && !destSpec.startsWith(Constants.R_REFS)) {
  596. // Assume the same kind of ref at the destination, e.g.
  597. // "refs/heads/foo:master", DWIMery assumes master is also
  598. // under "refs/heads/".
  599. //
  600. final String n = srcRef.getName();
  601. final int kindEnd = n.indexOf('/', Constants.R_REFS.length());
  602. destSpec = n.substring(0, kindEnd + 1) + destSpec;
  603. }
  604. final boolean forceUpdate = spec.isForceUpdate();
  605. final String localName = findTrackingRefName(destSpec, fetchSpecs);
  606. final RemoteRefUpdate rru = new RemoteRefUpdate(db, srcSpec,
  607. destSpec, forceUpdate, localName, null);
  608. result.add(rru);
  609. }
  610. return result;
  611. }
  612. private static Collection<RefSpec> expandPushWildcardsFor(
  613. final Repository db, final Collection<RefSpec> specs)
  614. throws IOException {
  615. final Map<String, Ref> localRefs = db.getRefDatabase().getRefs(ALL);
  616. final Collection<RefSpec> procRefs = new HashSet<RefSpec>();
  617. for (final RefSpec spec : specs) {
  618. if (spec.isWildcard()) {
  619. for (final Ref localRef : localRefs.values()) {
  620. if (spec.matchSource(localRef))
  621. procRefs.add(spec.expandFromSource(localRef));
  622. }
  623. } else {
  624. procRefs.add(spec);
  625. }
  626. }
  627. return procRefs;
  628. }
  629. private static String findTrackingRefName(final String remoteName,
  630. final Collection<RefSpec> fetchSpecs) {
  631. // try to find matching tracking refs
  632. for (final RefSpec fetchSpec : fetchSpecs) {
  633. if (fetchSpec.matchSource(remoteName)) {
  634. if (fetchSpec.isWildcard())
  635. return fetchSpec.expandFromSource(remoteName)
  636. .getDestination();
  637. else
  638. return fetchSpec.getDestination();
  639. }
  640. }
  641. return null;
  642. }
  643. /**
  644. * Default setting for {@link #fetchThin} option.
  645. */
  646. public static final boolean DEFAULT_FETCH_THIN = true;
  647. /**
  648. * Default setting for {@link #pushThin} option.
  649. */
  650. public static final boolean DEFAULT_PUSH_THIN = false;
  651. /**
  652. * Specification for fetch or push operations, to fetch or push all tags.
  653. * Acts as --tags.
  654. */
  655. public static final RefSpec REFSPEC_TAGS = new RefSpec(
  656. "refs/tags/*:refs/tags/*"); //$NON-NLS-1$
  657. /**
  658. * Specification for push operation, to push all refs under refs/heads. Acts
  659. * as --all.
  660. */
  661. public static final RefSpec REFSPEC_PUSH_ALL = new RefSpec(
  662. "refs/heads/*:refs/heads/*"); //$NON-NLS-1$
  663. /** The repository this transport fetches into, or pushes out of. */
  664. protected final Repository local;
  665. /** The URI used to create this transport. */
  666. protected final URIish uri;
  667. /** Name of the upload pack program, if it must be executed. */
  668. private String optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  669. /** Specifications to apply during fetch. */
  670. private List<RefSpec> fetch = Collections.emptyList();
  671. /**
  672. * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
  673. * <p>
  674. * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
  675. * tags during one-shot fetches used for later merges. This prevents
  676. * dragging down tags from repositories that we do not have established
  677. * tracking branches for. If we do not track the source repository, we most
  678. * likely do not care about any tags it publishes.
  679. */
  680. private TagOpt tagopt = TagOpt.NO_TAGS;
  681. /** Should fetch request thin-pack if remote repository can produce it. */
  682. private boolean fetchThin = DEFAULT_FETCH_THIN;
  683. /** Name of the receive pack program, if it must be executed. */
  684. private String optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  685. /** Specifications to apply during push. */
  686. private List<RefSpec> push = Collections.emptyList();
  687. /** Should push produce thin-pack when sending objects to remote repository. */
  688. private boolean pushThin = DEFAULT_PUSH_THIN;
  689. /** Should push just check for operation result, not really push. */
  690. private boolean dryRun;
  691. /** Should an incoming (fetch) transfer validate objects? */
  692. private ObjectChecker objectChecker;
  693. /** Should refs no longer on the source be pruned from the destination? */
  694. private boolean removeDeletedRefs;
  695. /** Timeout in seconds to wait before aborting an IO read or write. */
  696. private int timeout;
  697. /** Pack configuration used by this transport to make pack file. */
  698. private PackConfig packConfig;
  699. /** Assists with authentication the connection. */
  700. private CredentialsProvider credentialsProvider;
  701. /**
  702. * Create a new transport instance.
  703. *
  704. * @param local
  705. * the repository this instance will fetch into, or push out of.
  706. * This must be the repository passed to
  707. * {@link #open(Repository, URIish)}.
  708. * @param uri
  709. * the URI used to access the remote repository. This must be the
  710. * URI passed to {@link #open(Repository, URIish)}.
  711. */
  712. protected Transport(final Repository local, final URIish uri) {
  713. final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
  714. this.local = local;
  715. this.uri = uri;
  716. this.objectChecker = tc.newObjectChecker();
  717. this.credentialsProvider = CredentialsProvider.getDefault();
  718. }
  719. /**
  720. * Create a minimal transport instance not tied to a single repository.
  721. *
  722. * @param uri
  723. */
  724. protected Transport(final URIish uri) {
  725. this.uri = uri;
  726. this.local = null;
  727. this.objectChecker = new ObjectChecker();
  728. this.credentialsProvider = CredentialsProvider.getDefault();
  729. }
  730. /**
  731. * Get the URI this transport connects to.
  732. * <p>
  733. * Each transport instance connects to at most one URI at any point in time.
  734. *
  735. * @return the URI describing the location of the remote repository.
  736. */
  737. public URIish getURI() {
  738. return uri;
  739. }
  740. /**
  741. * Get the name of the remote executable providing upload-pack service.
  742. *
  743. * @return typically "git-upload-pack".
  744. */
  745. public String getOptionUploadPack() {
  746. return optionUploadPack;
  747. }
  748. /**
  749. * Set the name of the remote executable providing upload-pack services.
  750. *
  751. * @param where
  752. * name of the executable.
  753. */
  754. public void setOptionUploadPack(final String where) {
  755. if (where != null && where.length() > 0)
  756. optionUploadPack = where;
  757. else
  758. optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  759. }
  760. /**
  761. * Get the description of how annotated tags should be treated during fetch.
  762. *
  763. * @return option indicating the behavior of annotated tags in fetch.
  764. */
  765. public TagOpt getTagOpt() {
  766. return tagopt;
  767. }
  768. /**
  769. * Set the description of how annotated tags should be treated on fetch.
  770. *
  771. * @param option
  772. * method to use when handling annotated tags.
  773. */
  774. public void setTagOpt(final TagOpt option) {
  775. tagopt = option != null ? option : TagOpt.AUTO_FOLLOW;
  776. }
  777. /**
  778. * Default setting is: {@link #DEFAULT_FETCH_THIN}
  779. *
  780. * @return true if fetch should request thin-pack when possible; false
  781. * otherwise
  782. * @see PackTransport
  783. */
  784. public boolean isFetchThin() {
  785. return fetchThin;
  786. }
  787. /**
  788. * Set the thin-pack preference for fetch operation. Default setting is:
  789. * {@link #DEFAULT_FETCH_THIN}
  790. *
  791. * @param fetchThin
  792. * true when fetch should request thin-pack when possible; false
  793. * when it shouldn't
  794. * @see PackTransport
  795. */
  796. public void setFetchThin(final boolean fetchThin) {
  797. this.fetchThin = fetchThin;
  798. }
  799. /**
  800. * @return true if fetch will verify received objects are formatted
  801. * correctly. Validating objects requires more CPU time on the
  802. * client side of the connection.
  803. */
  804. public boolean isCheckFetchedObjects() {
  805. return getObjectChecker() != null;
  806. }
  807. /**
  808. * @param check
  809. * true to enable checking received objects; false to assume all
  810. * received objects are valid.
  811. * @see #setObjectChecker(ObjectChecker)
  812. */
  813. public void setCheckFetchedObjects(final boolean check) {
  814. if (check && objectChecker == null)
  815. setObjectChecker(new ObjectChecker());
  816. else if (!check && objectChecker != null)
  817. setObjectChecker(null);
  818. }
  819. /**
  820. * @return configured object checker for received objects, or null.
  821. * @since 3.6
  822. */
  823. public ObjectChecker getObjectChecker() {
  824. return objectChecker;
  825. }
  826. /**
  827. * @param impl
  828. * if non-null the object checking instance to verify each
  829. * received object with; null to disable object checking.
  830. * @since 3.6
  831. */
  832. public void setObjectChecker(ObjectChecker impl) {
  833. objectChecker = impl;
  834. }
  835. /**
  836. * Default setting is: {@link RemoteConfig#DEFAULT_RECEIVE_PACK}
  837. *
  838. * @return remote executable providing receive-pack service for pack
  839. * transports.
  840. * @see PackTransport
  841. */
  842. public String getOptionReceivePack() {
  843. return optionReceivePack;
  844. }
  845. /**
  846. * Set remote executable providing receive-pack service for pack transports.
  847. * Default setting is: {@link RemoteConfig#DEFAULT_RECEIVE_PACK}
  848. *
  849. * @param optionReceivePack
  850. * remote executable, if null or empty default one is set;
  851. */
  852. public void setOptionReceivePack(String optionReceivePack) {
  853. if (optionReceivePack != null && optionReceivePack.length() > 0)
  854. this.optionReceivePack = optionReceivePack;
  855. else
  856. this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  857. }
  858. /**
  859. * Default setting is: {@value #DEFAULT_PUSH_THIN}
  860. *
  861. * @return true if push should produce thin-pack in pack transports
  862. * @see PackTransport
  863. */
  864. public boolean isPushThin() {
  865. return pushThin;
  866. }
  867. /**
  868. * Set thin-pack preference for push operation. Default setting is:
  869. * {@value #DEFAULT_PUSH_THIN}
  870. *
  871. * @param pushThin
  872. * true when push should produce thin-pack in pack transports;
  873. * false when it shouldn't
  874. * @see PackTransport
  875. */
  876. public void setPushThin(final boolean pushThin) {
  877. this.pushThin = pushThin;
  878. }
  879. /**
  880. * @return true if destination refs should be removed if they no longer
  881. * exist at the source repository.
  882. */
  883. public boolean isRemoveDeletedRefs() {
  884. return removeDeletedRefs;
  885. }
  886. /**
  887. * Set whether or not to remove refs which no longer exist in the source.
  888. * <p>
  889. * If true, refs at the destination repository (local for fetch, remote for
  890. * push) are deleted if they no longer exist on the source side (remote for
  891. * fetch, local for push).
  892. * <p>
  893. * False by default, as this may cause data to become unreachable, and
  894. * eventually be deleted on the next GC.
  895. *
  896. * @param remove true to remove refs that no longer exist.
  897. */
  898. public void setRemoveDeletedRefs(final boolean remove) {
  899. removeDeletedRefs = remove;
  900. }
  901. /**
  902. * Apply provided remote configuration on this transport.
  903. *
  904. * @param cfg
  905. * configuration to apply on this transport.
  906. */
  907. public void applyConfig(final RemoteConfig cfg) {
  908. setOptionUploadPack(cfg.getUploadPack());
  909. setOptionReceivePack(cfg.getReceivePack());
  910. setTagOpt(cfg.getTagOpt());
  911. fetch = cfg.getFetchRefSpecs();
  912. push = cfg.getPushRefSpecs();
  913. timeout = cfg.getTimeout();
  914. }
  915. /**
  916. * @return true if push operation should just check for possible result and
  917. * not really update remote refs, false otherwise - when push should
  918. * act normally.
  919. */
  920. public boolean isDryRun() {
  921. return dryRun;
  922. }
  923. /**
  924. * Set dry run option for push operation.
  925. *
  926. * @param dryRun
  927. * true if push operation should just check for possible result
  928. * and not really update remote refs, false otherwise - when push
  929. * should act normally.
  930. */
  931. public void setDryRun(final boolean dryRun) {
  932. this.dryRun = dryRun;
  933. }
  934. /** @return timeout (in seconds) before aborting an IO operation. */
  935. public int getTimeout() {
  936. return timeout;
  937. }
  938. /**
  939. * Set the timeout before willing to abort an IO call.
  940. *
  941. * @param seconds
  942. * number of seconds to wait (with no data transfer occurring)
  943. * before aborting an IO read or write operation with this
  944. * remote.
  945. */
  946. public void setTimeout(final int seconds) {
  947. timeout = seconds;
  948. }
  949. /**
  950. * Get the configuration used by the pack generator to make packs.
  951. *
  952. * If {@link #setPackConfig(PackConfig)} was previously given null a new
  953. * PackConfig is created on demand by this method using the source
  954. * repository's settings.
  955. *
  956. * @return the pack configuration. Never null.
  957. */
  958. public PackConfig getPackConfig() {
  959. if (packConfig == null)
  960. packConfig = new PackConfig(local);
  961. return packConfig;
  962. }
  963. /**
  964. * Set the configuration used by the pack generator.
  965. *
  966. * @param pc
  967. * configuration controlling packing parameters. If null the
  968. * source repository's settings will be used.
  969. */
  970. public void setPackConfig(PackConfig pc) {
  971. packConfig = pc;
  972. }
  973. /**
  974. * A credentials provider to assist with authentication connections..
  975. *
  976. * @param credentialsProvider
  977. * the credentials provider, or null if there is none
  978. */
  979. public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
  980. this.credentialsProvider = credentialsProvider;
  981. }
  982. /**
  983. * The configured credentials provider.
  984. *
  985. * @return the credentials provider, or null if no credentials provider is
  986. * associated with this transport.
  987. */
  988. public CredentialsProvider getCredentialsProvider() {
  989. return credentialsProvider;
  990. }
  991. /**
  992. * Fetch objects and refs from the remote repository to the local one.
  993. * <p>
  994. * This is a utility function providing standard fetch behavior. Local
  995. * tracking refs associated with the remote repository are automatically
  996. * updated if this transport was created from a {@link RemoteConfig} with
  997. * fetch RefSpecs defined.
  998. *
  999. * @param monitor
  1000. * progress monitor to inform the user about our processing
  1001. * activity. Must not be null. Use {@link NullProgressMonitor} if
  1002. * progress updates are not interesting or necessary.
  1003. * @param toFetch
  1004. * specification of refs to fetch locally. May be null or the
  1005. * empty collection to use the specifications from the
  1006. * RemoteConfig. Source for each RefSpec can't be null.
  1007. * @return information describing the tracking refs updated.
  1008. * @throws NotSupportedException
  1009. * this transport implementation does not support fetching
  1010. * objects.
  1011. * @throws TransportException
  1012. * the remote connection could not be established or object
  1013. * copying (if necessary) failed or update specification was
  1014. * incorrect.
  1015. */
  1016. public FetchResult fetch(final ProgressMonitor monitor,
  1017. Collection<RefSpec> toFetch) throws NotSupportedException,
  1018. TransportException {
  1019. if (toFetch == null || toFetch.isEmpty()) {
  1020. // If the caller did not ask for anything use the defaults.
  1021. //
  1022. if (fetch.isEmpty())
  1023. throw new TransportException(JGitText.get().nothingToFetch);
  1024. toFetch = fetch;
  1025. } else if (!fetch.isEmpty()) {
  1026. // If the caller asked for something specific without giving
  1027. // us the local tracking branch see if we can update any of
  1028. // the local tracking branches without incurring additional
  1029. // object transfer overheads.
  1030. //
  1031. final Collection<RefSpec> tmp = new ArrayList<RefSpec>(toFetch);
  1032. for (final RefSpec requested : toFetch) {
  1033. final String reqSrc = requested.getSource();
  1034. for (final RefSpec configured : fetch) {
  1035. final String cfgSrc = configured.getSource();
  1036. final String cfgDst = configured.getDestination();
  1037. if (cfgSrc.equals(reqSrc) && cfgDst != null) {
  1038. tmp.add(configured);
  1039. break;
  1040. }
  1041. }
  1042. }
  1043. toFetch = tmp;
  1044. }
  1045. final FetchResult result = new FetchResult();
  1046. new FetchProcess(this, toFetch).execute(monitor, result);
  1047. return result;
  1048. }
  1049. /**
  1050. * Push objects and refs from the local repository to the remote one.
  1051. * <p>
  1052. * This is a utility function providing standard push behavior. It updates
  1053. * remote refs and send there necessary objects according to remote ref
  1054. * update specification. After successful remote ref update, associated
  1055. * locally stored tracking branch is updated if set up accordingly. Detailed
  1056. * operation result is provided after execution.
  1057. * <p>
  1058. * For setting up remote ref update specification from ref spec, see helper
  1059. * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1060. * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1061. * directly {@link RemoteRefUpdate} for more possibilities.
  1062. * <p>
  1063. * When {@link #isDryRun()} is true, result of this operation is just
  1064. * estimation of real operation result, no real action is performed.
  1065. *
  1066. * @see RemoteRefUpdate
  1067. *
  1068. * @param monitor
  1069. * progress monitor to inform the user about our processing
  1070. * activity. Must not be null. Use {@link NullProgressMonitor} if
  1071. * progress updates are not interesting or necessary.
  1072. * @param toPush
  1073. * specification of refs to push. May be null or the empty
  1074. * collection to use the specifications from the RemoteConfig
  1075. * converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1076. * more than 1 RemoteRefUpdate with the same remoteName is
  1077. * allowed. These objects are modified during this call.
  1078. * @param out
  1079. * output stream to write messages to
  1080. * @return information about results of remote refs updates, tracking refs
  1081. * updates and refs advertised by remote repository.
  1082. * @throws NotSupportedException
  1083. * this transport implementation does not support pushing
  1084. * objects.
  1085. * @throws TransportException
  1086. * the remote connection could not be established or object
  1087. * copying (if necessary) failed at I/O or protocol level or
  1088. * update specification was incorrect.
  1089. * @since 3.0
  1090. */
  1091. public PushResult push(final ProgressMonitor monitor,
  1092. Collection<RemoteRefUpdate> toPush, OutputStream out)
  1093. throws NotSupportedException,
  1094. TransportException {
  1095. if (toPush == null || toPush.isEmpty()) {
  1096. // If the caller did not ask for anything use the defaults.
  1097. try {
  1098. toPush = findRemoteRefUpdatesFor(push);
  1099. } catch (final IOException e) {
  1100. throw new TransportException(MessageFormat.format(
  1101. JGitText.get().problemWithResolvingPushRefSpecsLocally, e.getMessage()), e);
  1102. }
  1103. if (toPush.isEmpty())
  1104. throw new TransportException(JGitText.get().nothingToPush);
  1105. }
  1106. final PushProcess pushProcess = new PushProcess(this, toPush, out);
  1107. return pushProcess.execute(monitor);
  1108. }
  1109. /**
  1110. * Push objects and refs from the local repository to the remote one.
  1111. * <p>
  1112. * This is a utility function providing standard push behavior. It updates
  1113. * remote refs and sends necessary objects according to remote ref update
  1114. * specification. After successful remote ref update, associated locally
  1115. * stored tracking branch is updated if set up accordingly. Detailed
  1116. * operation result is provided after execution.
  1117. * <p>
  1118. * For setting up remote ref update specification from ref spec, see helper
  1119. * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1120. * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1121. * directly {@link RemoteRefUpdate} for more possibilities.
  1122. * <p>
  1123. * When {@link #isDryRun()} is true, result of this operation is just
  1124. * estimation of real operation result, no real action is performed.
  1125. *
  1126. * @see RemoteRefUpdate
  1127. *
  1128. * @param monitor
  1129. * progress monitor to inform the user about our processing
  1130. * activity. Must not be null. Use {@link NullProgressMonitor} if
  1131. * progress updates are not interesting or necessary.
  1132. * @param toPush
  1133. * specification of refs to push. May be null or the empty
  1134. * collection to use the specifications from the RemoteConfig
  1135. * converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1136. * more than 1 RemoteRefUpdate with the same remoteName is
  1137. * allowed. These objects are modified during this call.
  1138. *
  1139. * @return information about results of remote refs updates, tracking refs
  1140. * updates and refs advertised by remote repository.
  1141. * @throws NotSupportedException
  1142. * this transport implementation does not support pushing
  1143. * objects.
  1144. * @throws TransportException
  1145. * the remote connection could not be established or object
  1146. * copying (if necessary) failed at I/O or protocol level or
  1147. * update specification was incorrect.
  1148. */
  1149. public PushResult push(final ProgressMonitor monitor,
  1150. Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
  1151. TransportException {
  1152. return push(monitor, toPush, null);
  1153. }
  1154. /**
  1155. * Convert push remote refs update specification from {@link RefSpec} form
  1156. * to {@link RemoteRefUpdate}. Conversion expands wildcards by matching
  1157. * source part to local refs. expectedOldObjectId in RemoteRefUpdate is
  1158. * always set as null. Tracking branch is configured if RefSpec destination
  1159. * matches source of any fetch ref spec for this transport remote
  1160. * configuration.
  1161. * <p>
  1162. * Conversion is performed for context of this transport (database, fetch
  1163. * specifications).
  1164. *
  1165. * @param specs
  1166. * collection of RefSpec to convert.
  1167. * @return collection of set up {@link RemoteRefUpdate}.
  1168. * @throws IOException
  1169. * when problem occurred during conversion or specification set
  1170. * up: most probably, missing objects or refs.
  1171. */
  1172. public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1173. final Collection<RefSpec> specs) throws IOException {
  1174. return findRemoteRefUpdatesFor(local, specs, fetch);
  1175. }
  1176. /**
  1177. * Begins a new connection for fetching from the remote repository.
  1178. * <p>
  1179. * If the transport has no local repository, the fetch connection can only
  1180. * be used for reading remote refs.
  1181. *
  1182. * @return a fresh connection to fetch from the remote repository.
  1183. * @throws NotSupportedException
  1184. * the implementation does not support fetching.
  1185. * @throws TransportException
  1186. * the remote connection could not be established.
  1187. */
  1188. public abstract FetchConnection openFetch() throws NotSupportedException,
  1189. TransportException;
  1190. /**
  1191. * Begins a new connection for pushing into the remote repository.
  1192. *
  1193. * @return a fresh connection to push into the remote repository.
  1194. * @throws NotSupportedException
  1195. * the implementation does not support pushing.
  1196. * @throws TransportException
  1197. * the remote connection could not be established
  1198. */
  1199. public abstract PushConnection openPush() throws NotSupportedException,
  1200. TransportException;
  1201. /**
  1202. * Close any resources used by this transport.
  1203. * <p>
  1204. * If the remote repository is contacted by a network socket this method
  1205. * must close that network socket, disconnecting the two peers. If the
  1206. * remote repository is actually local (same system) this method must close
  1207. * any open file handles used to read the "remote" repository.
  1208. */
  1209. public abstract void close();
  1210. }