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