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 53KB

Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569
  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, 2020 Shawn O. Pearce <spearce@spearce.org> and others
  6. *
  7. * This program and the accompanying materials are made available under the
  8. * terms of the Eclipse Distribution License v. 1.0 which is available at
  9. * https://www.eclipse.org/org/documents/edl-v10.php.
  10. *
  11. * SPDX-License-Identifier: BSD-3-Clause
  12. */
  13. package org.eclipse.jgit.transport;
  14. import static java.nio.charset.StandardCharsets.UTF_8;
  15. import static java.util.Objects.requireNonNull;
  16. import java.io.BufferedReader;
  17. import java.io.IOException;
  18. import java.io.InputStreamReader;
  19. import java.io.OutputStream;
  20. import java.io.PrintStream;
  21. import java.lang.ref.WeakReference;
  22. import java.lang.reflect.Field;
  23. import java.lang.reflect.Modifier;
  24. import java.net.URISyntaxException;
  25. import java.net.URL;
  26. import java.text.MessageFormat;
  27. import java.util.ArrayList;
  28. import java.util.Collection;
  29. import java.util.Collections;
  30. import java.util.Enumeration;
  31. import java.util.LinkedHashSet;
  32. import java.util.LinkedList;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.Vector;
  36. import java.util.concurrent.CopyOnWriteArrayList;
  37. import org.eclipse.jgit.annotations.NonNull;
  38. import org.eclipse.jgit.annotations.Nullable;
  39. import org.eclipse.jgit.api.errors.AbortedByHookException;
  40. import org.eclipse.jgit.errors.NotSupportedException;
  41. import org.eclipse.jgit.errors.TransportException;
  42. import org.eclipse.jgit.hooks.Hooks;
  43. import org.eclipse.jgit.hooks.PrePushHook;
  44. import org.eclipse.jgit.internal.JGitText;
  45. import org.eclipse.jgit.lib.Constants;
  46. import org.eclipse.jgit.lib.ObjectChecker;
  47. import org.eclipse.jgit.lib.ObjectId;
  48. import org.eclipse.jgit.lib.ProgressMonitor;
  49. import org.eclipse.jgit.lib.Ref;
  50. import org.eclipse.jgit.lib.Repository;
  51. import org.eclipse.jgit.storage.pack.PackConfig;
  52. /**
  53. * Connects two Git repositories together and copies objects between them.
  54. * <p>
  55. * A transport can be used for either fetching (copying objects into the
  56. * caller's repository from the remote repository) or pushing (copying objects
  57. * into the remote repository from the caller's repository). Each transport
  58. * implementation is responsible for the details associated with establishing
  59. * the network connection(s) necessary for the copy, as well as actually
  60. * shuffling data back and forth.
  61. * <p>
  62. * Transport instances and the connections they create are not thread-safe.
  63. * Callers must ensure a transport is accessed by only one thread at a time.
  64. */
  65. public abstract class Transport implements AutoCloseable {
  66. /** Type of operation a Transport is being opened for. */
  67. public enum Operation {
  68. /** Transport is to fetch objects locally. */
  69. FETCH,
  70. /** Transport is to push objects remotely. */
  71. PUSH;
  72. }
  73. private static final List<WeakReference<TransportProtocol>> protocols =
  74. new CopyOnWriteArrayList<>();
  75. static {
  76. // Registration goes backwards in order of priority.
  77. register(TransportLocal.PROTO_LOCAL);
  78. register(TransportBundleFile.PROTO_BUNDLE);
  79. register(TransportAmazonS3.PROTO_S3);
  80. register(TransportGitAnon.PROTO_GIT);
  81. register(TransportSftp.PROTO_SFTP);
  82. register(TransportHttp.PROTO_FTP);
  83. register(TransportHttp.PROTO_HTTP);
  84. register(TransportGitSsh.PROTO_SSH);
  85. registerByService();
  86. }
  87. private static void registerByService() {
  88. ClassLoader ldr = Thread.currentThread().getContextClassLoader();
  89. if (ldr == null)
  90. ldr = Transport.class.getClassLoader();
  91. Enumeration<URL> catalogs = catalogs(ldr);
  92. while (catalogs.hasMoreElements())
  93. scan(ldr, catalogs.nextElement());
  94. }
  95. private static Enumeration<URL> catalogs(ClassLoader ldr) {
  96. try {
  97. String prefix = "META-INF/services/"; //$NON-NLS-1$
  98. String name = prefix + Transport.class.getName();
  99. return ldr.getResources(name);
  100. } catch (IOException err) {
  101. return new Vector<URL>().elements();
  102. }
  103. }
  104. private static void scan(ClassLoader ldr, URL url) {
  105. try (BufferedReader br = new BufferedReader(
  106. new InputStreamReader(url.openStream(), UTF_8))) {
  107. String line;
  108. while ((line = br.readLine()) != null) {
  109. line = line.trim();
  110. if (line.length() == 0)
  111. continue;
  112. int comment = line.indexOf('#');
  113. if (comment == 0)
  114. continue;
  115. if (comment != -1)
  116. line = line.substring(0, comment).trim();
  117. load(ldr, line);
  118. }
  119. } catch (IOException e) {
  120. // Ignore errors
  121. }
  122. }
  123. private static void load(ClassLoader ldr, String cn) {
  124. Class<?> clazz;
  125. try {
  126. clazz = Class.forName(cn, false, ldr);
  127. } catch (ClassNotFoundException notBuiltin) {
  128. // Doesn't exist, even though the service entry is present.
  129. //
  130. return;
  131. }
  132. for (Field f : clazz.getDeclaredFields()) {
  133. if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC
  134. && TransportProtocol.class.isAssignableFrom(f.getType())) {
  135. TransportProtocol proto;
  136. try {
  137. proto = (TransportProtocol) f.get(null);
  138. } catch (IllegalArgumentException | IllegalAccessException e) {
  139. // If we cannot access the field, don't.
  140. continue;
  141. }
  142. if (proto != null)
  143. register(proto);
  144. }
  145. }
  146. }
  147. /**
  148. * Register a TransportProtocol instance for use during open.
  149. * <p>
  150. * Protocol definitions are held by WeakReference, allowing them to be
  151. * garbage collected when the calling application drops all strongly held
  152. * references to the TransportProtocol. Therefore applications should use a
  153. * singleton pattern as described in
  154. * {@link org.eclipse.jgit.transport.TransportProtocol}'s class
  155. * documentation to ensure their protocol does not get disabled by garbage
  156. * collection earlier than expected.
  157. * <p>
  158. * The new protocol is registered in front of all earlier protocols, giving
  159. * it higher priority than the built-in protocol definitions.
  160. *
  161. * @param proto
  162. * the protocol definition. Must not be null.
  163. */
  164. public static void register(TransportProtocol proto) {
  165. protocols.add(0, new WeakReference<>(proto));
  166. }
  167. /**
  168. * Unregister a TransportProtocol instance.
  169. * <p>
  170. * Unregistering a protocol usually isn't necessary, as protocols are held
  171. * by weak references and will automatically clear when they are garbage
  172. * collected by the JVM. Matching is handled by reference equality, so the
  173. * exact reference given to {@link #register(TransportProtocol)} must be
  174. * used.
  175. *
  176. * @param proto
  177. * the exact object previously given to register.
  178. */
  179. public static void unregister(TransportProtocol proto) {
  180. for (WeakReference<TransportProtocol> ref : protocols) {
  181. TransportProtocol refProto = ref.get();
  182. if (refProto == null || refProto == proto)
  183. protocols.remove(ref);
  184. }
  185. }
  186. /**
  187. * Obtain a copy of the registered protocols.
  188. *
  189. * @return an immutable copy of the currently registered protocols.
  190. */
  191. public static List<TransportProtocol> getTransportProtocols() {
  192. int cnt = protocols.size();
  193. List<TransportProtocol> res = new ArrayList<>(cnt);
  194. for (WeakReference<TransportProtocol> ref : protocols) {
  195. TransportProtocol proto = ref.get();
  196. if (proto != null)
  197. res.add(proto);
  198. else
  199. protocols.remove(ref);
  200. }
  201. return Collections.unmodifiableList(res);
  202. }
  203. /**
  204. * Open a new transport instance to connect two repositories.
  205. * <p>
  206. * This method assumes
  207. * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  208. *
  209. * @param local
  210. * existing local repository.
  211. * @param remote
  212. * location of the remote repository - may be URI or remote
  213. * configuration name.
  214. * @return the new transport instance. Never null. In case of multiple URIs
  215. * in remote configuration, only the first is chosen.
  216. * @throws java.net.URISyntaxException
  217. * the location is not a remote defined in the configuration
  218. * file and is not a well-formed URL.
  219. * @throws org.eclipse.jgit.errors.NotSupportedException
  220. * the protocol specified is not supported.
  221. * @throws org.eclipse.jgit.errors.TransportException
  222. * the transport cannot open this URI.
  223. */
  224. public static Transport open(Repository local, String remote)
  225. throws NotSupportedException, URISyntaxException,
  226. TransportException {
  227. return open(local, remote, Operation.FETCH);
  228. }
  229. /**
  230. * Open a new transport instance to connect two repositories.
  231. *
  232. * @param local
  233. * existing local repository.
  234. * @param remote
  235. * location of the remote repository - may be URI or remote
  236. * configuration name.
  237. * @param op
  238. * planned use of the returned Transport; the URI may differ
  239. * based on the type of connection desired.
  240. * @return the new transport instance. Never null. In case of multiple URIs
  241. * in remote configuration, only the first is chosen.
  242. * @throws java.net.URISyntaxException
  243. * the location is not a remote defined in the configuration
  244. * file and is not a well-formed URL.
  245. * @throws org.eclipse.jgit.errors.NotSupportedException
  246. * the protocol specified is not supported.
  247. * @throws org.eclipse.jgit.errors.TransportException
  248. * the transport cannot open this URI.
  249. */
  250. public static Transport open(final Repository local, final String remote,
  251. final Operation op) throws NotSupportedException,
  252. URISyntaxException, TransportException {
  253. if (local != null) {
  254. final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  255. if (doesNotExist(cfg)) {
  256. return open(local, new URIish(remote), null);
  257. }
  258. return open(local, cfg, op);
  259. }
  260. return open(new URIish(remote));
  261. }
  262. /**
  263. * Open new transport instances to connect two repositories.
  264. * <p>
  265. * This method assumes
  266. * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  267. *
  268. * @param local
  269. * existing local repository.
  270. * @param remote
  271. * location of the remote repository - may be URI or remote
  272. * configuration name.
  273. * @return the list of new transport instances for every URI in remote
  274. * configuration.
  275. * @throws java.net.URISyntaxException
  276. * the location is not a remote defined in the configuration
  277. * file and is not a well-formed URL.
  278. * @throws org.eclipse.jgit.errors.NotSupportedException
  279. * the protocol specified is not supported.
  280. * @throws org.eclipse.jgit.errors.TransportException
  281. * the transport cannot open this URI.
  282. */
  283. public static List<Transport> openAll(final Repository local,
  284. final String remote) throws NotSupportedException,
  285. URISyntaxException, TransportException {
  286. return openAll(local, remote, Operation.FETCH);
  287. }
  288. /**
  289. * Open new transport instances to connect two repositories.
  290. *
  291. * @param local
  292. * existing local repository.
  293. * @param remote
  294. * location of the remote repository - may be URI or remote
  295. * configuration name.
  296. * @param op
  297. * planned use of the returned Transport; the URI may differ
  298. * based on the type of connection desired.
  299. * @return the list of new transport instances for every URI in remote
  300. * configuration.
  301. * @throws java.net.URISyntaxException
  302. * the location is not a remote defined in the configuration
  303. * file and is not a well-formed URL.
  304. * @throws org.eclipse.jgit.errors.NotSupportedException
  305. * the protocol specified is not supported.
  306. * @throws org.eclipse.jgit.errors.TransportException
  307. * the transport cannot open this URI.
  308. */
  309. public static List<Transport> openAll(final Repository local,
  310. final String remote, final Operation op)
  311. throws NotSupportedException, URISyntaxException,
  312. TransportException {
  313. final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  314. if (doesNotExist(cfg)) {
  315. final ArrayList<Transport> transports = new ArrayList<>(1);
  316. transports.add(open(local, new URIish(remote), null));
  317. return transports;
  318. }
  319. return openAll(local, cfg, op);
  320. }
  321. /**
  322. * Open a new transport instance to connect two repositories.
  323. * <p>
  324. * This method assumes
  325. * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  326. *
  327. * @param local
  328. * existing local repository.
  329. * @param cfg
  330. * configuration describing how to connect to the remote
  331. * repository.
  332. * @return the new transport instance. Never null. In case of multiple URIs
  333. * in remote configuration, only the first is chosen.
  334. * @throws org.eclipse.jgit.errors.NotSupportedException
  335. * the protocol specified is not supported.
  336. * @throws org.eclipse.jgit.errors.TransportException
  337. * the transport cannot open this URI.
  338. * @throws java.lang.IllegalArgumentException
  339. * if provided remote configuration doesn't have any URI
  340. * associated.
  341. */
  342. public static Transport open(Repository local, RemoteConfig cfg)
  343. throws NotSupportedException, TransportException {
  344. return open(local, cfg, Operation.FETCH);
  345. }
  346. /**
  347. * Open a new transport instance to connect two repositories.
  348. *
  349. * @param local
  350. * existing local repository.
  351. * @param cfg
  352. * configuration describing how to connect to the remote
  353. * repository.
  354. * @param op
  355. * planned use of the returned Transport; the URI may differ
  356. * based on the type of connection desired.
  357. * @return the new transport instance. Never null. In case of multiple URIs
  358. * in remote configuration, only the first is chosen.
  359. * @throws org.eclipse.jgit.errors.NotSupportedException
  360. * the protocol specified is not supported.
  361. * @throws org.eclipse.jgit.errors.TransportException
  362. * the transport cannot open this URI.
  363. * @throws java.lang.IllegalArgumentException
  364. * if provided remote configuration doesn't have any URI
  365. * associated.
  366. */
  367. public static Transport open(final Repository local,
  368. final RemoteConfig cfg, final Operation op)
  369. throws NotSupportedException, TransportException {
  370. final List<URIish> uris = getURIs(cfg, op);
  371. if (uris.isEmpty())
  372. throw new IllegalArgumentException(MessageFormat.format(
  373. JGitText.get().remoteConfigHasNoURIAssociated, cfg.getName()));
  374. final Transport tn = open(local, uris.get(0), cfg.getName());
  375. tn.applyConfig(cfg);
  376. return tn;
  377. }
  378. /**
  379. * Open new transport instances to connect two repositories.
  380. * <p>
  381. * This method assumes
  382. * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  383. *
  384. * @param local
  385. * existing local repository.
  386. * @param cfg
  387. * configuration describing how to connect to the remote
  388. * repository.
  389. * @return the list of new transport instances for every URI in remote
  390. * configuration.
  391. * @throws org.eclipse.jgit.errors.NotSupportedException
  392. * the protocol specified is not supported.
  393. * @throws org.eclipse.jgit.errors.TransportException
  394. * the transport cannot open this URI.
  395. */
  396. public static List<Transport> openAll(final Repository local,
  397. final RemoteConfig cfg) throws NotSupportedException,
  398. TransportException {
  399. return openAll(local, cfg, Operation.FETCH);
  400. }
  401. /**
  402. * Open new transport instances to connect two repositories.
  403. *
  404. * @param local
  405. * existing local repository.
  406. * @param cfg
  407. * configuration describing how to connect to the remote
  408. * repository.
  409. * @param op
  410. * planned use of the returned Transport; the URI may differ
  411. * based on the type of connection desired.
  412. * @return the list of new transport instances for every URI in remote
  413. * configuration.
  414. * @throws org.eclipse.jgit.errors.NotSupportedException
  415. * the protocol specified is not supported.
  416. * @throws org.eclipse.jgit.errors.TransportException
  417. * the transport cannot open this URI.
  418. */
  419. public static List<Transport> openAll(final Repository local,
  420. final RemoteConfig cfg, final Operation op)
  421. throws NotSupportedException, TransportException {
  422. final List<URIish> uris = getURIs(cfg, op);
  423. final List<Transport> transports = new ArrayList<>(uris.size());
  424. for (URIish uri : uris) {
  425. final Transport tn = open(local, uri, cfg.getName());
  426. tn.applyConfig(cfg);
  427. transports.add(tn);
  428. }
  429. return transports;
  430. }
  431. private static List<URIish> getURIs(final RemoteConfig cfg,
  432. final Operation op) {
  433. switch (op) {
  434. case FETCH:
  435. return cfg.getURIs();
  436. case PUSH: {
  437. List<URIish> uris = cfg.getPushURIs();
  438. if (uris.isEmpty())
  439. uris = cfg.getURIs();
  440. return uris;
  441. }
  442. default:
  443. throw new IllegalArgumentException(op.toString());
  444. }
  445. }
  446. private static boolean doesNotExist(RemoteConfig cfg) {
  447. return cfg.getURIs().isEmpty() && cfg.getPushURIs().isEmpty();
  448. }
  449. /**
  450. * Open a new transport instance to connect two repositories.
  451. *
  452. * @param local
  453. * existing local repository.
  454. * @param uri
  455. * location of the remote repository.
  456. * @return the new transport instance. Never null.
  457. * @throws org.eclipse.jgit.errors.NotSupportedException
  458. * the protocol specified is not supported.
  459. * @throws org.eclipse.jgit.errors.TransportException
  460. * the transport cannot open this URI.
  461. */
  462. public static Transport open(Repository local, URIish uri)
  463. throws NotSupportedException, TransportException {
  464. return open(local, uri, null);
  465. }
  466. /**
  467. * Open a new transport instance to connect two repositories.
  468. *
  469. * @param local
  470. * existing local repository.
  471. * @param uri
  472. * location of the remote repository.
  473. * @param remoteName
  474. * name of the remote, if the remote as configured in
  475. * {@code local}; otherwise null.
  476. * @return the new transport instance. Never null.
  477. * @throws org.eclipse.jgit.errors.NotSupportedException
  478. * the protocol specified is not supported.
  479. * @throws org.eclipse.jgit.errors.TransportException
  480. * the transport cannot open this URI.
  481. */
  482. public static Transport open(Repository local, URIish uri, String remoteName)
  483. throws NotSupportedException, TransportException {
  484. for (WeakReference<TransportProtocol> ref : protocols) {
  485. TransportProtocol proto = ref.get();
  486. if (proto == null) {
  487. protocols.remove(ref);
  488. continue;
  489. }
  490. if (proto.canHandle(uri, local, remoteName)) {
  491. Transport tn = proto.open(uri, local, remoteName);
  492. tn.prePush = Hooks.prePush(local, tn.hookOutRedirect);
  493. tn.prePush.setRemoteLocation(uri.toString());
  494. tn.prePush.setRemoteName(remoteName);
  495. return tn;
  496. }
  497. }
  498. throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  499. }
  500. /**
  501. * Open a new transport with no local repository.
  502. * <p>
  503. * Note that the resulting transport instance can not be used for fetching
  504. * or pushing, but only for reading remote refs.
  505. *
  506. * @param uri a {@link org.eclipse.jgit.transport.URIish} object.
  507. * @return new Transport instance
  508. * @throws org.eclipse.jgit.errors.NotSupportedException
  509. * @throws org.eclipse.jgit.errors.TransportException
  510. */
  511. public static Transport open(URIish uri) throws NotSupportedException, TransportException {
  512. for (WeakReference<TransportProtocol> ref : protocols) {
  513. TransportProtocol proto = ref.get();
  514. if (proto == null) {
  515. protocols.remove(ref);
  516. continue;
  517. }
  518. if (proto.canHandle(uri, null, null))
  519. return proto.open(uri);
  520. }
  521. throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  522. }
  523. /**
  524. * Convert push remote refs update specification from
  525. * {@link org.eclipse.jgit.transport.RefSpec} form to
  526. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  527. * wildcards by matching source part to local refs. expectedOldObjectId in
  528. * RemoteRefUpdate is set when specified in leases. Tracking branch is
  529. * configured if RefSpec destination matches source of any fetch ref spec
  530. * for this transport remote configuration.
  531. *
  532. * @param db
  533. * local database.
  534. * @param specs
  535. * collection of RefSpec to convert.
  536. * @param leases
  537. * map from ref to lease (containing expected old object id)
  538. * @param fetchSpecs
  539. * fetch specifications used for finding localtracking refs. May
  540. * be null or empty collection.
  541. * @return collection of set up
  542. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  543. * @throws java.io.IOException
  544. * when problem occurred during conversion or specification set
  545. * up: most probably, missing objects or refs.
  546. * @since 4.7
  547. */
  548. public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  549. final Repository db, final Collection<RefSpec> specs,
  550. final Map<String, RefLeaseSpec> leases,
  551. Collection<RefSpec> fetchSpecs) throws IOException {
  552. if (fetchSpecs == null)
  553. fetchSpecs = Collections.emptyList();
  554. final List<RemoteRefUpdate> result = new LinkedList<>();
  555. final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);
  556. for (RefSpec spec : procRefs) {
  557. String srcSpec = spec.getSource();
  558. final Ref srcRef = db.findRef(srcSpec);
  559. if (srcRef != null)
  560. srcSpec = srcRef.getName();
  561. String destSpec = spec.getDestination();
  562. if (destSpec == null) {
  563. // No destination (no-colon in ref-spec), DWIMery assumes src
  564. //
  565. destSpec = srcSpec;
  566. }
  567. if (srcRef != null && !destSpec.startsWith(Constants.R_REFS)) {
  568. // Assume the same kind of ref at the destination, e.g.
  569. // "refs/heads/foo:master", DWIMery assumes master is also
  570. // under "refs/heads/".
  571. //
  572. final String n = srcRef.getName();
  573. final int kindEnd = n.indexOf('/', Constants.R_REFS.length());
  574. destSpec = n.substring(0, kindEnd + 1) + destSpec;
  575. }
  576. final boolean forceUpdate = spec.isForceUpdate();
  577. final String localName = findTrackingRefName(destSpec, fetchSpecs);
  578. final RefLeaseSpec leaseSpec = leases.get(destSpec);
  579. final ObjectId expected = leaseSpec == null ? null :
  580. db.resolve(leaseSpec.getExpected());
  581. final RemoteRefUpdate rru = new RemoteRefUpdate(db, srcSpec,
  582. destSpec, forceUpdate, localName, expected);
  583. result.add(rru);
  584. }
  585. return result;
  586. }
  587. /**
  588. * Convert push remote refs update specification from
  589. * {@link org.eclipse.jgit.transport.RefSpec} form to
  590. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  591. * wildcards by matching source part to local refs. expectedOldObjectId in
  592. * RemoteRefUpdate is always set as null. Tracking branch is configured if
  593. * RefSpec destination matches source of any fetch ref spec for this
  594. * transport remote configuration.
  595. *
  596. * @param db
  597. * local database.
  598. * @param specs
  599. * collection of RefSpec to convert.
  600. * @param fetchSpecs
  601. * fetch specifications used for finding localtracking refs. May
  602. * be null or empty collection.
  603. * @return collection of set up
  604. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  605. * @throws java.io.IOException
  606. * when problem occurred during conversion or specification set
  607. * up: most probably, missing objects or refs.
  608. */
  609. public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  610. final Repository db, final Collection<RefSpec> specs,
  611. Collection<RefSpec> fetchSpecs) throws IOException {
  612. return findRemoteRefUpdatesFor(db, specs, Collections.emptyMap(),
  613. fetchSpecs);
  614. }
  615. private static Collection<RefSpec> expandPushWildcardsFor(
  616. final Repository db, final Collection<RefSpec> specs)
  617. throws IOException {
  618. final List<Ref> localRefs = db.getRefDatabase().getRefs();
  619. final Collection<RefSpec> procRefs = new LinkedHashSet<>();
  620. for (RefSpec spec : specs) {
  621. if (spec.isWildcard()) {
  622. for (Ref localRef : localRefs) {
  623. if (spec.matchSource(localRef))
  624. procRefs.add(spec.expandFromSource(localRef));
  625. }
  626. } else {
  627. procRefs.add(spec);
  628. }
  629. }
  630. return procRefs;
  631. }
  632. private static String findTrackingRefName(final String remoteName,
  633. final Collection<RefSpec> fetchSpecs) {
  634. // try to find matching tracking refs
  635. for (RefSpec fetchSpec : fetchSpecs) {
  636. if (fetchSpec.matchSource(remoteName)) {
  637. if (fetchSpec.isWildcard()) {
  638. return fetchSpec.expandFromSource(remoteName)
  639. .getDestination();
  640. }
  641. return fetchSpec.getDestination();
  642. }
  643. }
  644. return null;
  645. }
  646. /**
  647. * Default setting for {@link #fetchThin} option.
  648. */
  649. public static final boolean DEFAULT_FETCH_THIN = true;
  650. /**
  651. * Default setting for {@link #pushThin} option.
  652. */
  653. public static final boolean DEFAULT_PUSH_THIN = false;
  654. /**
  655. * Specification for fetch or push operations, to fetch or push all tags.
  656. * Acts as --tags.
  657. */
  658. public static final RefSpec REFSPEC_TAGS = new RefSpec(
  659. "refs/tags/*:refs/tags/*"); //$NON-NLS-1$
  660. /**
  661. * Specification for push operation, to push all refs under refs/heads. Acts
  662. * as --all.
  663. */
  664. public static final RefSpec REFSPEC_PUSH_ALL = new RefSpec(
  665. "refs/heads/*:refs/heads/*"); //$NON-NLS-1$
  666. /** The repository this transport fetches into, or pushes out of. */
  667. protected final Repository local;
  668. /** The URI used to create this transport. */
  669. protected final URIish uri;
  670. /** Name of the upload pack program, if it must be executed. */
  671. private String optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  672. /** Specifications to apply during fetch. */
  673. private List<RefSpec> fetch = Collections.emptyList();
  674. /**
  675. * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
  676. * <p>
  677. * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
  678. * tags during one-shot fetches used for later merges. This prevents
  679. * dragging down tags from repositories that we do not have established
  680. * tracking branches for. If we do not track the source repository, we most
  681. * likely do not care about any tags it publishes.
  682. */
  683. private TagOpt tagopt = TagOpt.NO_TAGS;
  684. /** Should fetch request thin-pack if remote repository can produce it. */
  685. private boolean fetchThin = DEFAULT_FETCH_THIN;
  686. /** Name of the receive pack program, if it must be executed. */
  687. private String optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  688. /** Specifications to apply during push. */
  689. private List<RefSpec> push = Collections.emptyList();
  690. /** Should push produce thin-pack when sending objects to remote repository. */
  691. private boolean pushThin = DEFAULT_PUSH_THIN;
  692. /** Should push be all-or-nothing atomic behavior? */
  693. private boolean pushAtomic;
  694. /** Should push just check for operation result, not really push. */
  695. private boolean dryRun;
  696. /** Should an incoming (fetch) transfer validate objects? */
  697. private ObjectChecker objectChecker;
  698. /** Should refs no longer on the source be pruned from the destination? */
  699. private boolean removeDeletedRefs;
  700. private FilterSpec filterSpec = FilterSpec.NO_FILTER;
  701. /** Timeout in seconds to wait before aborting an IO read or write. */
  702. private int timeout;
  703. /** Pack configuration used by this transport to make pack file. */
  704. private PackConfig packConfig;
  705. /** Assists with authentication the connection. */
  706. private CredentialsProvider credentialsProvider;
  707. /** The option strings associated with the push operation. */
  708. private List<String> pushOptions;
  709. private PrintStream hookOutRedirect;
  710. private PrePushHook prePush;
  711. @Nullable
  712. TransferConfig.ProtocolVersion protocol;
  713. /**
  714. * Create a new transport instance.
  715. *
  716. * @param local
  717. * the repository this instance will fetch into, or push out of.
  718. * This must be the repository passed to
  719. * {@link #open(Repository, URIish)}.
  720. * @param uri
  721. * the URI used to access the remote repository. This must be the
  722. * URI passed to {@link #open(Repository, URIish)}.
  723. */
  724. protected Transport(Repository local, URIish uri) {
  725. final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
  726. this.local = local;
  727. this.uri = uri;
  728. this.protocol = tc.protocolVersion;
  729. this.objectChecker = tc.newObjectChecker();
  730. this.credentialsProvider = CredentialsProvider.getDefault();
  731. prePush = Hooks.prePush(local, hookOutRedirect);
  732. }
  733. /**
  734. * Create a minimal transport instance not tied to a single repository.
  735. *
  736. * @param uri
  737. * a {@link org.eclipse.jgit.transport.URIish} object.
  738. */
  739. protected Transport(URIish uri) {
  740. this.uri = uri;
  741. this.local = null;
  742. this.objectChecker = new ObjectChecker();
  743. this.credentialsProvider = CredentialsProvider.getDefault();
  744. }
  745. /**
  746. * Get the URI this transport connects to.
  747. * <p>
  748. * Each transport instance connects to at most one URI at any point in time.
  749. *
  750. * @return the URI describing the location of the remote repository.
  751. */
  752. public URIish getURI() {
  753. return uri;
  754. }
  755. /**
  756. * Get the name of the remote executable providing upload-pack service.
  757. *
  758. * @return typically "git-upload-pack".
  759. */
  760. public String getOptionUploadPack() {
  761. return optionUploadPack;
  762. }
  763. /**
  764. * Set the name of the remote executable providing upload-pack services.
  765. *
  766. * @param where
  767. * name of the executable.
  768. */
  769. public void setOptionUploadPack(String where) {
  770. if (where != null && where.length() > 0)
  771. optionUploadPack = where;
  772. else
  773. optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  774. }
  775. /**
  776. * Get the description of how annotated tags should be treated during fetch.
  777. *
  778. * @return option indicating the behavior of annotated tags in fetch.
  779. */
  780. public TagOpt getTagOpt() {
  781. return tagopt;
  782. }
  783. /**
  784. * Set the description of how annotated tags should be treated on fetch.
  785. *
  786. * @param option
  787. * method to use when handling annotated tags.
  788. */
  789. public void setTagOpt(TagOpt option) {
  790. tagopt = option != null ? option : TagOpt.AUTO_FOLLOW;
  791. }
  792. /**
  793. * Default setting is: {@link #DEFAULT_FETCH_THIN}
  794. *
  795. * @return true if fetch should request thin-pack when possible; false
  796. * otherwise
  797. * @see PackTransport
  798. */
  799. public boolean isFetchThin() {
  800. return fetchThin;
  801. }
  802. /**
  803. * Set the thin-pack preference for fetch operation. Default setting is:
  804. * {@link #DEFAULT_FETCH_THIN}
  805. *
  806. * @param fetchThin
  807. * true when fetch should request thin-pack when possible; false
  808. * when it shouldn't
  809. * @see PackTransport
  810. */
  811. public void setFetchThin(boolean fetchThin) {
  812. this.fetchThin = fetchThin;
  813. }
  814. /**
  815. * Whether fetch will verify if received objects are formatted correctly.
  816. *
  817. * @return true if fetch will verify received objects are formatted
  818. * correctly. Validating objects requires more CPU time on the
  819. * client side of the connection.
  820. */
  821. public boolean isCheckFetchedObjects() {
  822. return getObjectChecker() != null;
  823. }
  824. /**
  825. * Configure if checking received objects is enabled
  826. *
  827. * @param check
  828. * true to enable checking received objects; false to assume all
  829. * received objects are valid.
  830. * @see #setObjectChecker(ObjectChecker)
  831. */
  832. public void setCheckFetchedObjects(boolean check) {
  833. if (check && objectChecker == null)
  834. setObjectChecker(new ObjectChecker());
  835. else if (!check && objectChecker != null)
  836. setObjectChecker(null);
  837. }
  838. /**
  839. * Get configured object checker for received objects
  840. *
  841. * @return configured object checker for received objects, or null.
  842. * @since 3.6
  843. */
  844. public ObjectChecker getObjectChecker() {
  845. return objectChecker;
  846. }
  847. /**
  848. * Set the object checker to verify each received object with
  849. *
  850. * @param impl
  851. * if non-null the object checking instance to verify each
  852. * received object with; null to disable object checking.
  853. * @since 3.6
  854. */
  855. public void setObjectChecker(ObjectChecker impl) {
  856. objectChecker = impl;
  857. }
  858. /**
  859. * Default setting is:
  860. * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  861. *
  862. * @return remote executable providing receive-pack service for pack
  863. * transports.
  864. * @see PackTransport
  865. */
  866. public String getOptionReceivePack() {
  867. return optionReceivePack;
  868. }
  869. /**
  870. * Set remote executable providing receive-pack service for pack transports.
  871. * Default setting is:
  872. * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  873. *
  874. * @param optionReceivePack
  875. * remote executable, if null or empty default one is set;
  876. */
  877. public void setOptionReceivePack(String optionReceivePack) {
  878. if (optionReceivePack != null && optionReceivePack.length() > 0)
  879. this.optionReceivePack = optionReceivePack;
  880. else
  881. this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  882. }
  883. /**
  884. * Default setting is: {@value #DEFAULT_PUSH_THIN}
  885. *
  886. * @return true if push should produce thin-pack in pack transports
  887. * @see PackTransport
  888. */
  889. public boolean isPushThin() {
  890. return pushThin;
  891. }
  892. /**
  893. * Set thin-pack preference for push operation. Default setting is:
  894. * {@value #DEFAULT_PUSH_THIN}
  895. *
  896. * @param pushThin
  897. * true when push should produce thin-pack in pack transports;
  898. * false when it shouldn't
  899. * @see PackTransport
  900. */
  901. public void setPushThin(boolean pushThin) {
  902. this.pushThin = pushThin;
  903. }
  904. /**
  905. * Default setting is false.
  906. *
  907. * @return true if push requires all-or-nothing atomic behavior.
  908. * @since 4.2
  909. */
  910. public boolean isPushAtomic() {
  911. return pushAtomic;
  912. }
  913. /**
  914. * Request atomic push (all references succeed, or none do).
  915. * <p>
  916. * Server must also support atomic push. If the server does not support the
  917. * feature the push will abort without making changes.
  918. *
  919. * @param atomic
  920. * true when push should be an all-or-nothing operation.
  921. * @see PackTransport
  922. * @since 4.2
  923. */
  924. public void setPushAtomic(boolean atomic) {
  925. this.pushAtomic = atomic;
  926. }
  927. /**
  928. * Whether destination refs should be removed if they no longer exist at the
  929. * source repository.
  930. *
  931. * @return true if destination refs should be removed if they no longer
  932. * exist at the source repository.
  933. */
  934. public boolean isRemoveDeletedRefs() {
  935. return removeDeletedRefs;
  936. }
  937. /**
  938. * Set whether or not to remove refs which no longer exist in the source.
  939. * <p>
  940. * If true, refs at the destination repository (local for fetch, remote for
  941. * push) are deleted if they no longer exist on the source side (remote for
  942. * fetch, local for push).
  943. * <p>
  944. * False by default, as this may cause data to become unreachable, and
  945. * eventually be deleted on the next GC.
  946. *
  947. * @param remove true to remove refs that no longer exist.
  948. */
  949. public void setRemoveDeletedRefs(boolean remove) {
  950. removeDeletedRefs = remove;
  951. }
  952. /**
  953. * @return the blob limit value set with {@link #setFilterBlobLimit} or
  954. * {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
  955. * was set
  956. * @since 5.0
  957. * @deprecated Use {@link #getFilterSpec()} instead
  958. */
  959. @Deprecated
  960. public final long getFilterBlobLimit() {
  961. return filterSpec.getBlobLimit();
  962. }
  963. /**
  964. * @param bytes exclude blobs of size greater than this
  965. * @since 5.0
  966. * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
  967. */
  968. @Deprecated
  969. public final void setFilterBlobLimit(long bytes) {
  970. setFilterSpec(FilterSpec.withBlobLimit(bytes));
  971. }
  972. /**
  973. * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
  974. * or {@link FilterSpec#NO_FILTER} if it was never invoked.
  975. * @since 5.4
  976. */
  977. public final FilterSpec getFilterSpec() {
  978. return filterSpec;
  979. }
  980. /**
  981. * @param filter a new filter to use for this transport
  982. * @since 5.4
  983. */
  984. public final void setFilterSpec(@NonNull FilterSpec filter) {
  985. filterSpec = requireNonNull(filter);
  986. }
  987. /**
  988. * Apply provided remote configuration on this transport.
  989. *
  990. * @param cfg
  991. * configuration to apply on this transport.
  992. */
  993. public void applyConfig(RemoteConfig cfg) {
  994. setOptionUploadPack(cfg.getUploadPack());
  995. setOptionReceivePack(cfg.getReceivePack());
  996. setTagOpt(cfg.getTagOpt());
  997. fetch = cfg.getFetchRefSpecs();
  998. push = cfg.getPushRefSpecs();
  999. timeout = cfg.getTimeout();
  1000. }
  1001. /**
  1002. * Whether push operation should just check for possible result and not
  1003. * really update remote refs
  1004. *
  1005. * @return true if push operation should just check for possible result and
  1006. * not really update remote refs, false otherwise - when push should
  1007. * act normally.
  1008. */
  1009. public boolean isDryRun() {
  1010. return dryRun;
  1011. }
  1012. /**
  1013. * Set dry run option for push operation.
  1014. *
  1015. * @param dryRun
  1016. * true if push operation should just check for possible result
  1017. * and not really update remote refs, false otherwise - when push
  1018. * should act normally.
  1019. */
  1020. public void setDryRun(boolean dryRun) {
  1021. this.dryRun = dryRun;
  1022. }
  1023. /**
  1024. * Get timeout (in seconds) before aborting an IO operation.
  1025. *
  1026. * @return timeout (in seconds) before aborting an IO operation.
  1027. */
  1028. public int getTimeout() {
  1029. return timeout;
  1030. }
  1031. /**
  1032. * Set the timeout before willing to abort an IO call.
  1033. *
  1034. * @param seconds
  1035. * number of seconds to wait (with no data transfer occurring)
  1036. * before aborting an IO read or write operation with this
  1037. * remote.
  1038. */
  1039. public void setTimeout(int seconds) {
  1040. timeout = seconds;
  1041. }
  1042. /**
  1043. * Get the configuration used by the pack generator to make packs.
  1044. *
  1045. * If {@link #setPackConfig(PackConfig)} was previously given null a new
  1046. * PackConfig is created on demand by this method using the source
  1047. * repository's settings.
  1048. *
  1049. * @return the pack configuration. Never null.
  1050. */
  1051. public PackConfig getPackConfig() {
  1052. if (packConfig == null)
  1053. packConfig = new PackConfig(local);
  1054. return packConfig;
  1055. }
  1056. /**
  1057. * Set the configuration used by the pack generator.
  1058. *
  1059. * @param pc
  1060. * configuration controlling packing parameters. If null the
  1061. * source repository's settings will be used.
  1062. */
  1063. public void setPackConfig(PackConfig pc) {
  1064. packConfig = pc;
  1065. }
  1066. /**
  1067. * A credentials provider to assist with authentication connections..
  1068. *
  1069. * @param credentialsProvider
  1070. * the credentials provider, or null if there is none
  1071. */
  1072. public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
  1073. this.credentialsProvider = credentialsProvider;
  1074. }
  1075. /**
  1076. * The configured credentials provider.
  1077. *
  1078. * @return the credentials provider, or null if no credentials provider is
  1079. * associated with this transport.
  1080. */
  1081. public CredentialsProvider getCredentialsProvider() {
  1082. return credentialsProvider;
  1083. }
  1084. /**
  1085. * Get the option strings associated with the push operation
  1086. *
  1087. * @return the option strings associated with the push operation
  1088. * @since 4.5
  1089. */
  1090. public List<String> getPushOptions() {
  1091. return pushOptions;
  1092. }
  1093. /**
  1094. * Sets the option strings associated with the push operation.
  1095. *
  1096. * @param pushOptions
  1097. * null if push options are unsupported
  1098. * @since 4.5
  1099. */
  1100. public void setPushOptions(List<String> pushOptions) {
  1101. this.pushOptions = pushOptions;
  1102. }
  1103. /**
  1104. * Fetch objects and refs from the remote repository to the local one.
  1105. * <p>
  1106. * This is a utility function providing standard fetch behavior. Local
  1107. * tracking refs associated with the remote repository are automatically
  1108. * updated if this transport was created from a
  1109. * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1110. * defined.
  1111. *
  1112. * @param monitor
  1113. * progress monitor to inform the user about our processing
  1114. * activity. Must not be null. Use
  1115. * {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1116. * updates are not interesting or necessary.
  1117. * @param toFetch
  1118. * specification of refs to fetch locally. May be null or the
  1119. * empty collection to use the specifications from the
  1120. * RemoteConfig. Source for each RefSpec can't be null.
  1121. * @return information describing the tracking refs updated.
  1122. * @throws org.eclipse.jgit.errors.NotSupportedException
  1123. * this transport implementation does not support fetching
  1124. * objects.
  1125. * @throws org.eclipse.jgit.errors.TransportException
  1126. * the remote connection could not be established or object
  1127. * copying (if necessary) failed or update specification was
  1128. * incorrect.
  1129. * @since 5.11
  1130. */
  1131. public FetchResult fetch(final ProgressMonitor monitor,
  1132. Collection<RefSpec> toFetch)
  1133. throws NotSupportedException, TransportException {
  1134. return fetch(monitor, toFetch, null);
  1135. }
  1136. /**
  1137. * Fetch objects and refs from the remote repository to the local one.
  1138. * <p>
  1139. * This is a utility function providing standard fetch behavior. Local
  1140. * tracking refs associated with the remote repository are automatically
  1141. * updated if this transport was created from a
  1142. * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1143. * defined.
  1144. *
  1145. * @param monitor
  1146. * progress monitor to inform the user about our processing
  1147. * activity. Must not be null. Use
  1148. * {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1149. * updates are not interesting or necessary.
  1150. * @param toFetch
  1151. * specification of refs to fetch locally. May be null or the
  1152. * empty collection to use the specifications from the
  1153. * RemoteConfig. Source for each RefSpec can't be null.
  1154. * @param branch
  1155. * the initial branch to check out when cloning the repository.
  1156. * Can be specified as ref name (<code>refs/heads/master</code>),
  1157. * branch name (<code>master</code>) or tag name
  1158. * (<code>v1.2.3</code>). The default is to use the branch
  1159. * pointed to by the cloned repository's HEAD and can be
  1160. * requested by passing {@code null} or <code>HEAD</code>.
  1161. * @return information describing the tracking refs updated.
  1162. * @throws org.eclipse.jgit.errors.NotSupportedException
  1163. * this transport implementation does not support fetching
  1164. * objects.
  1165. * @throws org.eclipse.jgit.errors.TransportException
  1166. * the remote connection could not be established or object
  1167. * copying (if necessary) failed or update specification was
  1168. * incorrect.
  1169. * @since 5.11
  1170. */
  1171. public FetchResult fetch(final ProgressMonitor monitor,
  1172. Collection<RefSpec> toFetch, String branch)
  1173. throws NotSupportedException,
  1174. TransportException {
  1175. if (toFetch == null || toFetch.isEmpty()) {
  1176. // If the caller did not ask for anything use the defaults.
  1177. //
  1178. if (fetch.isEmpty())
  1179. throw new TransportException(JGitText.get().nothingToFetch);
  1180. toFetch = fetch;
  1181. } else if (!fetch.isEmpty()) {
  1182. // If the caller asked for something specific without giving
  1183. // us the local tracking branch see if we can update any of
  1184. // the local tracking branches without incurring additional
  1185. // object transfer overheads.
  1186. //
  1187. final Collection<RefSpec> tmp = new ArrayList<>(toFetch);
  1188. for (RefSpec requested : toFetch) {
  1189. final String reqSrc = requested.getSource();
  1190. for (RefSpec configured : fetch) {
  1191. final String cfgSrc = configured.getSource();
  1192. final String cfgDst = configured.getDestination();
  1193. if (cfgSrc.equals(reqSrc) && cfgDst != null) {
  1194. tmp.add(configured);
  1195. break;
  1196. }
  1197. }
  1198. }
  1199. toFetch = tmp;
  1200. }
  1201. final FetchResult result = new FetchResult();
  1202. new FetchProcess(this, toFetch).execute(monitor, result, branch);
  1203. local.autoGC(monitor);
  1204. return result;
  1205. }
  1206. /**
  1207. * Push objects and refs from the local repository to the remote one.
  1208. * <p>
  1209. * This is a utility function providing standard push behavior. It updates
  1210. * remote refs and send there necessary objects according to remote ref
  1211. * update specification. After successful remote ref update, associated
  1212. * locally stored tracking branch is updated if set up accordingly. Detailed
  1213. * operation result is provided after execution.
  1214. * <p>
  1215. * For setting up remote ref update specification from ref spec, see helper
  1216. * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1217. * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1218. * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1219. * possibilities.
  1220. * <p>
  1221. * When {@link #isDryRun()} is true, result of this operation is just
  1222. * estimation of real operation result, no real action is performed.
  1223. *
  1224. * @see RemoteRefUpdate
  1225. * @param monitor
  1226. * progress monitor to inform the user about our processing
  1227. * activity. Must not be null. Use
  1228. * {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1229. * updates are not interesting or necessary.
  1230. * @param toPush
  1231. * specification of refs to push. May be null or the empty
  1232. * collection to use the specifications from the RemoteConfig
  1233. * converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1234. * more than 1 RemoteRefUpdate with the same remoteName is
  1235. * allowed. These objects are modified during this call.
  1236. * @param out
  1237. * output stream to write messages to
  1238. * @return information about results of remote refs updates, tracking refs
  1239. * updates and refs advertised by remote repository.
  1240. * @throws org.eclipse.jgit.errors.NotSupportedException
  1241. * this transport implementation does not support pushing
  1242. * objects.
  1243. * @throws org.eclipse.jgit.errors.TransportException
  1244. * the remote connection could not be established or object
  1245. * copying (if necessary) failed at I/O or protocol level or
  1246. * update specification was incorrect.
  1247. * @since 3.0
  1248. */
  1249. public PushResult push(final ProgressMonitor monitor,
  1250. Collection<RemoteRefUpdate> toPush, OutputStream out)
  1251. throws NotSupportedException,
  1252. TransportException {
  1253. if (toPush == null || toPush.isEmpty()) {
  1254. // If the caller did not ask for anything use the defaults.
  1255. try {
  1256. toPush = findRemoteRefUpdatesFor(push);
  1257. } catch (final IOException e) {
  1258. throw new TransportException(MessageFormat.format(
  1259. JGitText.get().problemWithResolvingPushRefSpecsLocally, e.getMessage()), e);
  1260. }
  1261. if (toPush.isEmpty())
  1262. throw new TransportException(JGitText.get().nothingToPush);
  1263. }
  1264. if (prePush != null) {
  1265. try {
  1266. prePush.setRefs(toPush);
  1267. prePush.call();
  1268. } catch (AbortedByHookException | IOException e) {
  1269. throw new TransportException(e.getMessage(), e);
  1270. }
  1271. }
  1272. final PushProcess pushProcess = new PushProcess(this, toPush, out);
  1273. return pushProcess.execute(monitor);
  1274. }
  1275. /**
  1276. * Push objects and refs from the local repository to the remote one.
  1277. * <p>
  1278. * This is a utility function providing standard push behavior. It updates
  1279. * remote refs and sends necessary objects according to remote ref update
  1280. * specification. After successful remote ref update, associated locally
  1281. * stored tracking branch is updated if set up accordingly. Detailed
  1282. * operation result is provided after execution.
  1283. * <p>
  1284. * For setting up remote ref update specification from ref spec, see helper
  1285. * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1286. * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1287. * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1288. * possibilities.
  1289. * <p>
  1290. * When {@link #isDryRun()} is true, result of this operation is just
  1291. * estimation of real operation result, no real action is performed.
  1292. *
  1293. * @see RemoteRefUpdate
  1294. * @param monitor
  1295. * progress monitor to inform the user about our processing
  1296. * activity. Must not be null. Use
  1297. * {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1298. * updates are not interesting or necessary.
  1299. * @param toPush
  1300. * specification of refs to push. May be null or the empty
  1301. * collection to use the specifications from the RemoteConfig
  1302. * converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1303. * more than 1 RemoteRefUpdate with the same remoteName is
  1304. * allowed. These objects are modified during this call.
  1305. * @return information about results of remote refs updates, tracking refs
  1306. * updates and refs advertised by remote repository.
  1307. * @throws org.eclipse.jgit.errors.NotSupportedException
  1308. * this transport implementation does not support pushing
  1309. * objects.
  1310. * @throws org.eclipse.jgit.errors.TransportException
  1311. * the remote connection could not be established or object
  1312. * copying (if necessary) failed at I/O or protocol level or
  1313. * update specification was incorrect.
  1314. */
  1315. public PushResult push(final ProgressMonitor monitor,
  1316. Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
  1317. TransportException {
  1318. return push(monitor, toPush, null);
  1319. }
  1320. /**
  1321. * Convert push remote refs update specification from
  1322. * {@link org.eclipse.jgit.transport.RefSpec} form to
  1323. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1324. * wildcards by matching source part to local refs. expectedOldObjectId in
  1325. * RemoteRefUpdate is always set as null. Tracking branch is configured if
  1326. * RefSpec destination matches source of any fetch ref spec for this
  1327. * transport remote configuration.
  1328. * <p>
  1329. * Conversion is performed for context of this transport (database, fetch
  1330. * specifications).
  1331. *
  1332. * @param specs
  1333. * collection of RefSpec to convert.
  1334. * @return collection of set up
  1335. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1336. * @throws java.io.IOException
  1337. * when problem occurred during conversion or specification set
  1338. * up: most probably, missing objects or refs.
  1339. */
  1340. public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1341. final Collection<RefSpec> specs) throws IOException {
  1342. return findRemoteRefUpdatesFor(local, specs, Collections.emptyMap(),
  1343. fetch);
  1344. }
  1345. /**
  1346. * Convert push remote refs update specification from
  1347. * {@link org.eclipse.jgit.transport.RefSpec} form to
  1348. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1349. * wildcards by matching source part to local refs. expectedOldObjectId in
  1350. * RemoteRefUpdate is set according to leases. Tracking branch is configured
  1351. * if RefSpec destination matches source of any fetch ref spec for this
  1352. * transport remote configuration.
  1353. * <p>
  1354. * Conversion is performed for context of this transport (database, fetch
  1355. * specifications).
  1356. *
  1357. * @param specs
  1358. * collection of RefSpec to convert.
  1359. * @param leases
  1360. * map from ref to lease (containing expected old object id)
  1361. * @return collection of set up
  1362. * {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1363. * @throws java.io.IOException
  1364. * when problem occurred during conversion or specification set
  1365. * up: most probably, missing objects or refs.
  1366. * @since 4.7
  1367. */
  1368. public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1369. final Collection<RefSpec> specs,
  1370. final Map<String, RefLeaseSpec> leases) throws IOException {
  1371. return findRemoteRefUpdatesFor(local, specs, leases,
  1372. fetch);
  1373. }
  1374. /**
  1375. * Begins a new connection for fetching from the remote repository.
  1376. * <p>
  1377. * If the transport has no local repository, the fetch connection can only
  1378. * be used for reading remote refs.
  1379. *
  1380. * @return a fresh connection to fetch from the remote repository.
  1381. * @throws org.eclipse.jgit.errors.NotSupportedException
  1382. * the implementation does not support fetching.
  1383. * @throws org.eclipse.jgit.errors.TransportException
  1384. * the remote connection could not be established.
  1385. */
  1386. public abstract FetchConnection openFetch() throws NotSupportedException,
  1387. TransportException;
  1388. /**
  1389. * Begins a new connection for fetching from the remote repository.
  1390. * <p>
  1391. * If the transport has no local repository, the fetch connection can only
  1392. * be used for reading remote refs.
  1393. * </p>
  1394. * <p>
  1395. * If the server supports git protocol V2, the {@link RefSpec}s and the
  1396. * additional patterns, if any, are used to restrict the server's ref
  1397. * advertisement to matching refs only.
  1398. * </p>
  1399. * <p>
  1400. * Transports that want to support git protocol V2 <em>must</em> override
  1401. * this; the default implementation ignores its arguments and calls
  1402. * {@link #openFetch()}.
  1403. * </p>
  1404. *
  1405. * @param refSpecs
  1406. * that will be fetched via
  1407. * {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
  1408. * @param additionalPatterns
  1409. * that will be set as ref prefixes if the server supports git
  1410. * protocol V2; {@code null} values are ignored
  1411. *
  1412. * @return a fresh connection to fetch from the remote repository.
  1413. * @throws org.eclipse.jgit.errors.NotSupportedException
  1414. * the implementation does not support fetching.
  1415. * @throws org.eclipse.jgit.errors.TransportException
  1416. * the remote connection could not be established.
  1417. * @since 5.11
  1418. */
  1419. public FetchConnection openFetch(Collection<RefSpec> refSpecs,
  1420. String... additionalPatterns)
  1421. throws NotSupportedException, TransportException {
  1422. return openFetch();
  1423. }
  1424. /**
  1425. * Begins a new connection for pushing into the remote repository.
  1426. *
  1427. * @return a fresh connection to push into the remote repository.
  1428. * @throws org.eclipse.jgit.errors.NotSupportedException
  1429. * the implementation does not support pushing.
  1430. * @throws org.eclipse.jgit.errors.TransportException
  1431. * the remote connection could not be established
  1432. */
  1433. public abstract PushConnection openPush() throws NotSupportedException,
  1434. TransportException;
  1435. /**
  1436. * {@inheritDoc}
  1437. * <p>
  1438. * Close any resources used by this transport.
  1439. * <p>
  1440. * If the remote repository is contacted by a network socket this method
  1441. * must close that network socket, disconnecting the two peers. If the
  1442. * remote repository is actually local (same system) this method must close
  1443. * any open file handles used to read the "remote" repository.
  1444. * <p>
  1445. * {@code AutoClosable.close()} declares that it throws {@link Exception}.
  1446. * Implementers shouldn't throw checked exceptions. This override narrows
  1447. * the signature to prevent them from doing so.
  1448. */
  1449. @Override
  1450. public abstract void close();
  1451. }