View Javadoc
1   /*
2    * Copyright (C) 2011, Christoph Brill <egore911@egore911.de>
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package org.eclipse.jgit.api;
44  
45  import java.net.URISyntaxException;
46  import java.text.MessageFormat;
47  import java.util.ArrayList;
48  import java.util.Collection;
49  import java.util.Collections;
50  import java.util.HashMap;
51  import java.util.Map;
52  
53  import org.eclipse.jgit.api.errors.GitAPIException;
54  import org.eclipse.jgit.api.errors.InvalidRemoteException;
55  import org.eclipse.jgit.api.errors.JGitInternalException;
56  import org.eclipse.jgit.errors.NotSupportedException;
57  import org.eclipse.jgit.errors.TransportException;
58  import org.eclipse.jgit.internal.JGitText;
59  import org.eclipse.jgit.lib.Constants;
60  import org.eclipse.jgit.lib.Ref;
61  import org.eclipse.jgit.lib.Repository;
62  import org.eclipse.jgit.transport.FetchConnection;
63  import org.eclipse.jgit.transport.RefSpec;
64  import org.eclipse.jgit.transport.Transport;
65  import org.eclipse.jgit.transport.URIish;
66  
67  /**
68   * The ls-remote command
69   *
70   * @see <a
71   *      href="http://www.kernel.org/pub/software/scm/git/docs/git-ls-remote.html"
72   *      >Git documentation about ls-remote</a>
73   */
74  public class LsRemoteCommand extends
75  		TransportCommand<LsRemoteCommand, Collection<Ref>> {
76  
77  	private String remote = Constants.DEFAULT_REMOTE_NAME;
78  
79  	private boolean heads;
80  
81  	private boolean tags;
82  
83  	private String uploadPack;
84  
85  	/**
86  	 * Constructor for LsRemoteCommand
87  	 *
88  	 * @param repo
89  	 *            local repository or null for operation without local
90  	 *            repository
91  	 */
92  	public LsRemoteCommand(Repository repo) {
93  		super(repo);
94  	}
95  
96  	/**
97  	 * The remote (uri or name) used for the fetch operation. If no remote is
98  	 * set, the default value of <code>Constants.DEFAULT_REMOTE_NAME</code> will
99  	 * be used.
100 	 *
101 	 * @see Constants#DEFAULT_REMOTE_NAME
102 	 * @param remote
103 	 *            a {@link java.lang.String} object.
104 	 * @return {@code this}
105 	 */
106 	public LsRemoteCommand setRemote(String remote) {
107 		checkCallable();
108 		this.remote = remote;
109 		return this;
110 	}
111 
112 	/**
113 	 * Include refs/heads in references results
114 	 *
115 	 * @param heads
116 	 *            whether to include refs/heads
117 	 * @return {@code this}
118 	 */
119 	public LsRemoteCommand setHeads(boolean heads) {
120 		this.heads = heads;
121 		return this;
122 	}
123 
124 	/**
125 	 * Include refs/tags in references results
126 	 *
127 	 * @param tags
128 	 *            whether to include tags
129 	 * @return {@code this}
130 	 */
131 	public LsRemoteCommand setTags(boolean tags) {
132 		this.tags = tags;
133 		return this;
134 	}
135 
136 	/**
137 	 * The full path of git-upload-pack on the remote host
138 	 *
139 	 * @param uploadPack
140 	 *            the full path of executable providing the git-upload-pack
141 	 *            service on remote host
142 	 * @return {@code this}
143 	 */
144 	public LsRemoteCommand setUploadPack(String uploadPack) {
145 		this.uploadPack = uploadPack;
146 		return this;
147 	}
148 
149 	/**
150 	 * {@inheritDoc}
151 	 * <p>
152 	 * Execute the {@code LsRemote} command with all the options and parameters
153 	 * collected by the setter methods (e.g. {@link #setHeads(boolean)}) of this
154 	 * class. Each instance of this class should only be used for one invocation
155 	 * of the command. Don't call this method twice on an instance.
156 	 */
157 	@Override
158 	public Collection<Ref> call() throws GitAPIException,
159 			InvalidRemoteException,
160 			org.eclipse.jgit.api.errors.TransportException {
161 		return execute().values();
162 	}
163 
164 	/**
165 	 * Same as {@link #call()}, but return Map instead of Collection.
166 	 *
167 	 * @return a map from names to references in the remote repository
168 	 * @throws org.eclipse.jgit.api.errors.GitAPIException
169 	 *             or subclass thereof when an error occurs
170 	 * @throws org.eclipse.jgit.api.errors.InvalidRemoteException
171 	 *             when called with an invalid remote uri
172 	 * @throws org.eclipse.jgit.api.errors.TransportException
173 	 *             for errors that occurs during transport
174 	 * @since 3.5
175 	 */
176 	public Map<String, Ref> callAsMap() throws GitAPIException,
177 			InvalidRemoteException,
178 			org.eclipse.jgit.api.errors.TransportException {
179 		return Collections.unmodifiableMap(execute());
180 	}
181 
182 	private Map<String, Ref> execute() throws GitAPIException,
183 			InvalidRemoteException,
184 			org.eclipse.jgit.api.errors.TransportException {
185 		checkCallable();
186 
187 		try (Transport transport = repo != null
188 				? Transport.open(repo, remote)
189 				: Transport.open(new URIish(remote))) {
190 			transport.setOptionUploadPack(uploadPack);
191 			configure(transport);
192 			Collection<RefSpec> refSpecs = new ArrayList<>(1);
193 			if (tags)
194 				refSpecs.add(new RefSpec(
195 						"refs/tags/*:refs/remotes/origin/tags/*")); //$NON-NLS-1$
196 			if (heads)
197 				refSpecs.add(new RefSpec("refs/heads/*:refs/remotes/origin/*")); //$NON-NLS-1$
198 			Collection<Ref> refs;
199 			Map<String, Ref> refmap = new HashMap<>();
200 			try (FetchConnection fc = transport.openFetch()) {
201 				refs = fc.getRefs();
202 				if (refSpecs.isEmpty())
203 					for (Ref r : refs)
204 						refmap.put(r.getName(), r);
205 				else
206 					for (Ref r : refs)
207 						for (RefSpec rs : refSpecs)
208 							if (rs.matchSource(r)) {
209 								refmap.put(r.getName(), r);
210 								break;
211 							}
212 				return refmap;
213 			}
214 		} catch (URISyntaxException e) {
215 			throw new InvalidRemoteException(MessageFormat.format(
216 					JGitText.get().invalidRemote, remote));
217 		} catch (NotSupportedException e) {
218 			throw new JGitInternalException(
219 					JGitText.get().exceptionCaughtDuringExecutionOfLsRemoteCommand,
220 					e);
221 		} catch (TransportException e) {
222 			throw new org.eclipse.jgit.api.errors.TransportException(
223 					e.getMessage(),
224 					e);
225 		}
226 	}
227 
228 }