Evaluate short refnames into full names during push
[egit/imyousuf.git] / org.spearce.jgit / src / org / spearce / jgit / transport / Transport.java
bloba0a25751ba20bab22d4de6db249448cd69eb81cb
1 /*
2 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or
9 * without modification, are permitted provided that the following
10 * conditions are met:
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
20 * - Neither the name of the Git Development Community nor the
21 * names of its contributors may be used to endorse or promote
22 * products derived from this software without specific prior
23 * written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 package org.spearce.jgit.transport;
42 import java.io.IOException;
43 import java.net.URISyntaxException;
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.LinkedList;
49 import java.util.List;
50 import java.util.Map;
52 import org.spearce.jgit.errors.NotSupportedException;
53 import org.spearce.jgit.errors.TransportException;
54 import org.spearce.jgit.lib.Constants;
55 import org.spearce.jgit.lib.NullProgressMonitor;
56 import org.spearce.jgit.lib.ProgressMonitor;
57 import org.spearce.jgit.lib.Ref;
58 import org.spearce.jgit.lib.Repository;
59 import org.spearce.jgit.lib.TransferConfig;
61 /**
62 * Connects two Git repositories together and copies objects between them.
63 * <p>
64 * A transport can be used for either fetching (copying objects into the
65 * caller's repository from the remote repository) or pushing (copying objects
66 * into the remote repository from the caller's repository). Each transport
67 * implementation is responsible for the details associated with establishing
68 * the network connection(s) necessary for the copy, as well as actually
69 * shuffling data back and forth.
70 * <p>
71 * Transport instances and the connections they create are not thread-safe.
72 * Callers must ensure a transport is accessed by only one thread at a time.
74 public abstract class Transport {
75 /**
76 * Open a new transport instance to connect two repositories.
78 * @param local
79 * existing local repository.
80 * @param remote
81 * location of the remote repository - may be URI or remote
82 * configuration name.
83 * @return the new transport instance. Never null. In case of multiple URIs
84 * in remote configuration, only the first is chosen.
85 * @throws URISyntaxException
86 * the location is not a remote defined in the configuration
87 * file and is not a well-formed URL.
88 * @throws NotSupportedException
89 * the protocol specified is not supported.
91 public static Transport open(final Repository local, final String remote)
92 throws NotSupportedException, URISyntaxException {
93 final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
94 final List<URIish> uris = cfg.getURIs();
95 if (uris.size() == 0)
96 return open(local, new URIish(remote));
97 return open(local, cfg);
101 * Open new transport instances to connect two repositories.
103 * @param local
104 * existing local repository.
105 * @param remote
106 * location of the remote repository - may be URI or remote
107 * configuration name.
108 * @return the list of new transport instances for every URI in remote
109 * configuration.
110 * @throws URISyntaxException
111 * the location is not a remote defined in the configuration
112 * file and is not a well-formed URL.
113 * @throws NotSupportedException
114 * the protocol specified is not supported.
116 public static List<Transport> openAll(final Repository local,
117 final String remote) throws NotSupportedException,
118 URISyntaxException {
119 final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
120 final List<URIish> uris = cfg.getURIs();
121 if (uris.size() == 0) {
122 final ArrayList<Transport> transports = new ArrayList<Transport>(1);
123 transports.add(open(local, new URIish(remote)));
124 return transports;
126 return openAll(local, cfg);
130 * Open a new transport instance to connect two repositories.
132 * @param local
133 * existing local repository.
134 * @param cfg
135 * configuration describing how to connect to the remote
136 * repository.
137 * @return the new transport instance. Never null. In case of multiple URIs
138 * in remote configuration, only the first is chosen.
139 * @throws NotSupportedException
140 * the protocol specified is not supported.
141 * @throws IllegalArgumentException
142 * if provided remote configuration doesn't have any URI
143 * associated.
145 public static Transport open(final Repository local, final RemoteConfig cfg)
146 throws NotSupportedException {
147 if (cfg.getURIs().isEmpty())
148 throw new IllegalArgumentException(
149 "Remote config \""
150 + cfg.getName() + "\" has no URIs associated");
151 final Transport tn = open(local, cfg.getURIs().get(0));
152 tn.applyConfig(cfg);
153 return tn;
157 * Open new transport instances to connect two repositories.
159 * @param local
160 * existing local repository.
161 * @param cfg
162 * configuration describing how to connect to the remote
163 * repository.
164 * @return the list of new transport instances for every URI in remote
165 * configuration.
166 * @throws NotSupportedException
167 * the protocol specified is not supported.
169 public static List<Transport> openAll(final Repository local,
170 final RemoteConfig cfg) throws NotSupportedException {
171 final List<URIish> uris = cfg.getURIs();
172 final List<Transport> transports = new ArrayList<Transport>(uris.size());
173 for (final URIish uri : uris) {
174 final Transport tn = open(local, uri);
175 tn.applyConfig(cfg);
176 transports.add(tn);
178 return transports;
182 * Open a new transport instance to connect two repositories.
184 * @param local
185 * existing local repository.
186 * @param remote
187 * location of the remote repository.
188 * @return the new transport instance. Never null.
189 * @throws NotSupportedException
190 * the protocol specified is not supported.
192 public static Transport open(final Repository local, final URIish remote)
193 throws NotSupportedException {
194 if (TransportGitSsh.canHandle(remote))
195 return new TransportGitSsh(local, remote);
197 else if (TransportHttp.canHandle(remote))
198 return new TransportHttp(local, remote);
200 else if (TransportSftp.canHandle(remote))
201 return new TransportSftp(local, remote);
203 else if (TransportGitAnon.canHandle(remote))
204 return new TransportGitAnon(local, remote);
206 else if (TransportAmazonS3.canHandle(remote))
207 return new TransportAmazonS3(local, remote);
209 else if (TransportBundleFile.canHandle(remote))
210 return new TransportBundleFile(local, remote);
212 else if (TransportLocal.canHandle(remote))
213 return new TransportLocal(local, remote);
215 throw new NotSupportedException("URI not supported: " + remote);
219 * Convert push remote refs update specification from {@link RefSpec} form
220 * to {@link RemoteRefUpdate}. Conversion expands wildcards by matching
221 * source part to local refs. expectedOldObjectId in RemoteRefUpdate is
222 * always set as null. Tracking branch is configured if RefSpec destination
223 * matches source of any fetch ref spec for this transport remote
224 * configuration.
226 * @param db
227 * local database.
228 * @param specs
229 * collection of RefSpec to convert.
230 * @param fetchSpecs
231 * fetch specifications used for finding localtracking refs. May
232 * be null or empty collection.
233 * @return collection of set up {@link RemoteRefUpdate}.
234 * @throws IOException
235 * when problem occurred during conversion or specification set
236 * up: most probably, missing objects or refs.
238 public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
239 final Repository db, final Collection<RefSpec> specs,
240 Collection<RefSpec> fetchSpecs) throws IOException {
241 if (fetchSpecs == null)
242 fetchSpecs = Collections.emptyList();
243 final List<RemoteRefUpdate> result = new LinkedList<RemoteRefUpdate>();
244 final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);
246 for (final RefSpec spec : procRefs) {
247 String srcRef = spec.getSource();
248 final Ref src = db.getRef(srcRef);
249 if (src != null)
250 srcRef = src.getName();
251 String remoteName = spec.getDestination();
252 // null destination (no-colon in ref-spec) is a special case
253 if (remoteName == null) {
254 remoteName = srcRef;
255 } else {
256 if (!remoteName.startsWith(Constants.R_REFS)) {
257 // null source is another special case (delete)
258 if (srcRef != null) {
259 // assume the same type of ref at the destination
260 String srcPrefix = srcRef.substring(0, srcRef.indexOf('/', Constants.R_REFS.length()));
261 remoteName = srcPrefix + "/" + remoteName;
265 final boolean forceUpdate = spec.isForceUpdate();
266 final String localName = findTrackingRefName(remoteName, fetchSpecs);
268 final RemoteRefUpdate rru = new RemoteRefUpdate(db, srcRef,
269 remoteName, forceUpdate, localName, null);
270 result.add(rru);
272 return result;
275 private static Collection<RefSpec> expandPushWildcardsFor(
276 final Repository db, final Collection<RefSpec> specs) {
277 final Map<String, Ref> localRefs = db.getAllRefs();
278 final Collection<RefSpec> procRefs = new HashSet<RefSpec>();
280 for (final RefSpec spec : specs) {
281 if (spec.isWildcard()) {
282 for (final Ref localRef : localRefs.values()) {
283 if (spec.matchSource(localRef))
284 procRefs.add(spec.expandFromSource(localRef));
286 } else {
287 procRefs.add(spec);
290 return procRefs;
293 private static String findTrackingRefName(final String remoteName,
294 final Collection<RefSpec> fetchSpecs) {
295 // try to find matching tracking refs
296 for (final RefSpec fetchSpec : fetchSpecs) {
297 if (fetchSpec.matchSource(remoteName)) {
298 if (fetchSpec.isWildcard())
299 return fetchSpec.expandFromSource(remoteName)
300 .getDestination();
301 else
302 return fetchSpec.getDestination();
305 return null;
309 * Default setting for {@link #fetchThin} option.
311 public static final boolean DEFAULT_FETCH_THIN = true;
314 * Default setting for {@link #pushThin} option.
316 public static final boolean DEFAULT_PUSH_THIN = false;
319 * Specification for fetch or push operations, to fetch or push all tags.
320 * Acts as --tags.
322 public static final RefSpec REFSPEC_TAGS = new RefSpec(
323 "refs/tags/*:refs/tags/*");
326 * Specification for push operation, to push all refs under refs/heads. Acts
327 * as --all.
329 public static final RefSpec REFSPEC_PUSH_ALL = new RefSpec(
330 "refs/heads/*:refs/heads/*");
332 /** The repository this transport fetches into, or pushes out of. */
333 protected final Repository local;
335 /** The URI used to create this transport. */
336 protected final URIish uri;
338 /** Name of the upload pack program, if it must be executed. */
339 private String optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
341 /** Specifications to apply during fetch. */
342 private List<RefSpec> fetch = Collections.emptyList();
345 * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
346 * <p>
347 * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
348 * tags during one-shot fetches used for later merges. This prevents
349 * dragging down tags from repositories that we do not have established
350 * tracking branches for. If we do not track the source repository, we most
351 * likely do not care about any tags it publishes.
353 private TagOpt tagopt = TagOpt.NO_TAGS;
355 /** Should fetch request thin-pack if remote repository can produce it. */
356 private boolean fetchThin = DEFAULT_FETCH_THIN;
358 /** Name of the receive pack program, if it must be executed. */
359 private String optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
361 /** Specifications to apply during push. */
362 private List<RefSpec> push = Collections.emptyList();
364 /** Should push produce thin-pack when sending objects to remote repository. */
365 private boolean pushThin = DEFAULT_PUSH_THIN;
367 /** Should push just check for operation result, not really push. */
368 private boolean dryRun;
370 /** Should an incoming (fetch) transfer validate objects? */
371 private boolean checkFetchedObjects;
373 /** Should refs no longer on the source be pruned from the destination? */
374 private boolean removeDeletedRefs;
377 * Create a new transport instance.
379 * @param local
380 * the repository this instance will fetch into, or push out of.
381 * This must be the repository passed to
382 * {@link #open(Repository, URIish)}.
383 * @param uri
384 * the URI used to access the remote repository. This must be the
385 * URI passed to {@link #open(Repository, URIish)}.
387 protected Transport(final Repository local, final URIish uri) {
388 final TransferConfig tc = local.getConfig().getTransfer();
389 this.local = local;
390 this.uri = uri;
391 this.checkFetchedObjects = tc.isFsckObjects();
395 * Get the URI this transport connects to.
396 * <p>
397 * Each transport instance connects to at most one URI at any point in time.
399 * @return the URI describing the location of the remote repository.
401 public URIish getURI() {
402 return uri;
406 * Get the name of the remote executable providing upload-pack service.
408 * @return typically "git-upload-pack".
410 public String getOptionUploadPack() {
411 return optionUploadPack;
415 * Set the name of the remote executable providing upload-pack services.
417 * @param where
418 * name of the executable.
420 public void setOptionUploadPack(final String where) {
421 if (where != null && where.length() > 0)
422 optionUploadPack = where;
423 else
424 optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
428 * Get the description of how annotated tags should be treated during fetch.
430 * @return option indicating the behavior of annotated tags in fetch.
432 public TagOpt getTagOpt() {
433 return tagopt;
437 * Set the description of how annotated tags should be treated on fetch.
439 * @param option
440 * method to use when handling annotated tags.
442 public void setTagOpt(final TagOpt option) {
443 tagopt = option != null ? option : TagOpt.AUTO_FOLLOW;
447 * Default setting is: {@link #DEFAULT_FETCH_THIN}
449 * @return true if fetch should request thin-pack when possible; false
450 * otherwise
451 * @see PackTransport
453 public boolean isFetchThin() {
454 return fetchThin;
458 * Set the thin-pack preference for fetch operation. Default setting is:
459 * {@link #DEFAULT_FETCH_THIN}
461 * @param fetchThin
462 * true when fetch should request thin-pack when possible; false
463 * when it shouldn't
464 * @see PackTransport
466 public void setFetchThin(final boolean fetchThin) {
467 this.fetchThin = fetchThin;
471 * @return true if fetch will verify received objects are formatted
472 * correctly. Validating objects requires more CPU time on the
473 * client side of the connection.
475 public boolean isCheckFetchedObjects() {
476 return checkFetchedObjects;
480 * @param check
481 * true to enable checking received objects; false to assume all
482 * received objects are valid.
484 public void setCheckFetchedObjects(final boolean check) {
485 checkFetchedObjects = check;
489 * Default setting is: {@value RemoteConfig#DEFAULT_RECEIVE_PACK}
491 * @return remote executable providing receive-pack service for pack
492 * transports.
493 * @see PackTransport
495 public String getOptionReceivePack() {
496 return optionReceivePack;
500 * Set remote executable providing receive-pack service for pack transports.
501 * Default setting is: {@value RemoteConfig#DEFAULT_RECEIVE_PACK}
503 * @param optionReceivePack
504 * remote executable, if null or empty default one is set;
506 public void setOptionReceivePack(String optionReceivePack) {
507 if (optionReceivePack != null && optionReceivePack.length() > 0)
508 this.optionReceivePack = optionReceivePack;
509 else
510 this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
514 * Default setting is: {@value #DEFAULT_PUSH_THIN}
516 * @return true if push should produce thin-pack in pack transports
517 * @see PackTransport
519 public boolean isPushThin() {
520 return pushThin;
524 * Set thin-pack preference for push operation. Default setting is:
525 * {@value #DEFAULT_PUSH_THIN}
527 * @param pushThin
528 * true when push should produce thin-pack in pack transports;
529 * false when it shouldn't
530 * @see PackTransport
532 public void setPushThin(final boolean pushThin) {
533 this.pushThin = pushThin;
537 * @return true if destination refs should be removed if they no longer
538 * exist at the source repository.
540 public boolean isRemoveDeletedRefs() {
541 return removeDeletedRefs;
545 * Set whether or not to remove refs which no longer exist in the source.
546 * <p>
547 * If true, refs at the destination repository (local for fetch, remote for
548 * push) are deleted if they no longer exist on the source side (remote for
549 * fetch, local for push).
550 * <p>
551 * False by default, as this may cause data to become unreachable, and
552 * eventually be deleted on the next GC.
554 * @param remove true to remove refs that no longer exist.
556 public void setRemoveDeletedRefs(final boolean remove) {
557 removeDeletedRefs = remove;
561 * Apply provided remote configuration on this transport.
563 * @param cfg
564 * configuration to apply on this transport.
566 public void applyConfig(final RemoteConfig cfg) {
567 setOptionUploadPack(cfg.getUploadPack());
568 fetch = cfg.getFetchRefSpecs();
569 setTagOpt(cfg.getTagOpt());
570 optionReceivePack = cfg.getReceivePack();
571 push = cfg.getPushRefSpecs();
575 * @return true if push operation should just check for possible result and
576 * not really update remote refs, false otherwise - when push should
577 * act normally.
579 public boolean isDryRun() {
580 return dryRun;
584 * Set dry run option for push operation.
586 * @param dryRun
587 * true if push operation should just check for possible result
588 * and not really update remote refs, false otherwise - when push
589 * should act normally.
591 public void setDryRun(final boolean dryRun) {
592 this.dryRun = dryRun;
596 * Fetch objects and refs from the remote repository to the local one.
597 * <p>
598 * This is a utility function providing standard fetch behavior. Local
599 * tracking refs associated with the remote repository are automatically
600 * updated if this transport was created from a {@link RemoteConfig} with
601 * fetch RefSpecs defined.
603 * @param monitor
604 * progress monitor to inform the user about our processing
605 * activity. Must not be null. Use {@link NullProgressMonitor} if
606 * progress updates are not interesting or necessary.
607 * @param toFetch
608 * specification of refs to fetch locally. May be null or the
609 * empty collection to use the specifications from the
610 * RemoteConfig. Source for each RefSpec can't be null.
611 * @return information describing the tracking refs updated.
612 * @throws NotSupportedException
613 * this transport implementation does not support fetching
614 * objects.
615 * @throws TransportException
616 * the remote connection could not be established or object
617 * copying (if necessary) failed or update specification was
618 * incorrect.
620 public FetchResult fetch(final ProgressMonitor monitor,
621 Collection<RefSpec> toFetch) throws NotSupportedException,
622 TransportException {
623 if (toFetch == null || toFetch.isEmpty()) {
624 // If the caller did not ask for anything use the defaults.
626 if (fetch.isEmpty())
627 throw new TransportException("Nothing to fetch.");
628 toFetch = fetch;
629 } else if (!fetch.isEmpty()) {
630 // If the caller asked for something specific without giving
631 // us the local tracking branch see if we can update any of
632 // the local tracking branches without incurring additional
633 // object transfer overheads.
635 final Collection<RefSpec> tmp = new ArrayList<RefSpec>(toFetch);
636 for (final RefSpec requested : toFetch) {
637 final String reqSrc = requested.getSource();
638 for (final RefSpec configured : fetch) {
639 final String cfgSrc = configured.getSource();
640 final String cfgDst = configured.getDestination();
641 if (cfgSrc.equals(reqSrc) && cfgDst != null) {
642 tmp.add(configured);
643 break;
647 toFetch = tmp;
650 final FetchResult result = new FetchResult();
651 new FetchProcess(this, toFetch).execute(monitor, result);
652 return result;
656 * Push objects and refs from the local repository to the remote one.
657 * <p>
658 * This is a utility function providing standard push behavior. It updates
659 * remote refs and send there necessary objects according to remote ref
660 * update specification. After successful remote ref update, associated
661 * locally stored tracking branch is updated if set up accordingly. Detailed
662 * operation result is provided after execution.
663 * <p>
664 * For setting up remote ref update specification from ref spec, see helper
665 * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
666 * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
667 * directly {@link RemoteRefUpdate} for more possibilities.
668 * <p>
669 * When {@link #isDryRun()} is true, result of this operation is just
670 * estimation of real operation result, no real action is performed.
672 * @see RemoteRefUpdate
674 * @param monitor
675 * progress monitor to inform the user about our processing
676 * activity. Must not be null. Use {@link NullProgressMonitor} if
677 * progress updates are not interesting or necessary.
678 * @param toPush
679 * specification of refs to push. May be null or the empty
680 * collection to use the specifications from the RemoteConfig
681 * converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
682 * more than 1 RemoteRefUpdate with the same remoteName is
683 * allowed. These objects are modified during this call.
684 * @return information about results of remote refs updates, tracking refs
685 * updates and refs advertised by remote repository.
686 * @throws NotSupportedException
687 * this transport implementation does not support pushing
688 * objects.
689 * @throws TransportException
690 * the remote connection could not be established or object
691 * copying (if necessary) failed at I/O or protocol level or
692 * update specification was incorrect.
694 public PushResult push(final ProgressMonitor monitor,
695 Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
696 TransportException {
697 if (toPush == null || toPush.isEmpty()) {
698 // If the caller did not ask for anything use the defaults.
699 try {
700 toPush = findRemoteRefUpdatesFor(push);
701 } catch (final IOException e) {
702 throw new TransportException(
703 "Problem with resolving push ref specs locally: "
704 + e.getMessage(), e);
706 if (toPush.isEmpty())
707 throw new TransportException("Nothing to push.");
709 final PushProcess pushProcess = new PushProcess(this, toPush);
710 return pushProcess.execute(monitor);
714 * Convert push remote refs update specification from {@link RefSpec} form
715 * to {@link RemoteRefUpdate}. Conversion expands wildcards by matching
716 * source part to local refs. expectedOldObjectId in RemoteRefUpdate is
717 * always set as null. Tracking branch is configured if RefSpec destination
718 * matches source of any fetch ref spec for this transport remote
719 * configuration.
720 * <p>
721 * Conversion is performed for context of this transport (database, fetch
722 * specifications).
724 * @param specs
725 * collection of RefSpec to convert.
726 * @return collection of set up {@link RemoteRefUpdate}.
727 * @throws IOException
728 * when problem occurred during conversion or specification set
729 * up: most probably, missing objects or refs.
731 public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
732 final Collection<RefSpec> specs) throws IOException {
733 return findRemoteRefUpdatesFor(local, specs, fetch);
737 * Begins a new connection for fetching from the remote repository.
739 * @return a fresh connection to fetch from the remote repository.
740 * @throws NotSupportedException
741 * the implementation does not support fetching.
742 * @throws TransportException
743 * the remote connection could not be established.
745 public abstract FetchConnection openFetch() throws NotSupportedException,
746 TransportException;
749 * Begins a new connection for pushing into the remote repository.
751 * @return a fresh connection to push into the remote repository.
752 * @throws NotSupportedException
753 * the implementation does not support pushing.
754 * @throws TransportException
755 * the remote connection could not be established
757 public abstract PushConnection openPush() throws NotSupportedException,
758 TransportException;
761 * Close any resources used by this transport.
762 * <p>
763 * If the remote repository is contacted by a network socket this method
764 * must close that network socket, disconnecting the two peers. If the
765 * remote repository is actually local (same system) this method must close
766 * any open file handles used to read the "remote" repository.
768 public abstract void close();