View Javadoc
1   /*
2    * Copyright (C) 2018, Google LLC.
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.transport;
44  
45  import static java.util.Objects.requireNonNull;
46  
47  import java.util.ArrayList;
48  import java.util.Collections;
49  import java.util.HashSet;
50  import java.util.List;
51  import java.util.Set;
52  
53  import org.eclipse.jgit.annotations.NonNull;
54  import org.eclipse.jgit.annotations.Nullable;
55  import org.eclipse.jgit.lib.ObjectId;
56  
57  /**
58   * Fetch request from git protocol v2.
59   *
60   * <p>
61   * This is used as an input to {@link ProtocolV2Hook}.
62   *
63   * @since 5.1
64   */
65  public final class FetchV2Request extends FetchRequest {
66  	private final List<ObjectId> peerHas;
67  
68  	private final List<String> wantedRefs;
69  
70  	private final boolean doneReceived;
71  
72  	@NonNull
73  	private final List<String> serverOptions;
74  
75  	FetchV2Request(@NonNull List<ObjectId> peerHas,
76  			@NonNull List<String> wantedRefs,
77  			@NonNull Set<ObjectId> wantIds,
78  			@NonNull Set<ObjectId> clientShallowCommits, int deepenSince,
79  			@NonNull List<String> deepenNotRefs, int depth,
80  			long filterBlobLimit,
81  			boolean doneReceived, @NonNull Set<String> clientCapabilities,
82  			@Nullable String agent, @NonNull List<String> serverOptions) {
83  		super(wantIds, depth, clientShallowCommits, filterBlobLimit,
84  				clientCapabilities, deepenSince, deepenNotRefs, agent);
85  		this.peerHas = requireNonNull(peerHas);
86  		this.wantedRefs = requireNonNull(wantedRefs);
87  		this.doneReceived = doneReceived;
88  		this.serverOptions = requireNonNull(serverOptions);
89  	}
90  
91  	/**
92  	 * @return object ids received in the "have" lines
93  	 */
94  	@NonNull
95  	List<ObjectId> getPeerHas() {
96  		return peerHas;
97  	}
98  
99  	/**
100 	 * @return list of references received in "want-ref" lines
101 	 */
102 	@NonNull
103 	List<String> getWantedRefs() {
104 		return wantedRefs;
105 	}
106 
107 	/**
108 	 * @return true if the request had a "done" line
109 	 */
110 	boolean wasDoneReceived() {
111 		return doneReceived;
112 	}
113 
114 	/**
115 	 * Options received in server-option lines. The caller can choose to act on
116 	 * these in an application-specific way
117 	 *
118 	 * @return Immutable list of server options received in the request
119 	 *
120 	 * @since 5.2
121 	 */
122 	@NonNull
123 	public List<String> getServerOptions() {
124 		return serverOptions;
125 	}
126 
127 	/** @return A builder of {@link FetchV2Request}. */
128 	static Builder builder() {
129 		return new Builder();
130 	}
131 
132 	/** A builder for {@link FetchV2Request}. */
133 	static final class Builder {
134 		final List<ObjectId> peerHas = new ArrayList<>();
135 
136 		final List<String> wantedRefs = new ArrayList<>();
137 
138 		final Set<ObjectId> wantIds = new HashSet<>();
139 
140 		final Set<ObjectId> clientShallowCommits = new HashSet<>();
141 
142 		final List<String> deepenNotRefs = new ArrayList<>();
143 
144 		final Set<String> clientCapabilities = new HashSet<>();
145 
146 		int depth;
147 
148 		int deepenSince;
149 
150 		long filterBlobLimit = -1;
151 
152 		boolean doneReceived;
153 
154 		@Nullable
155 		String agent;
156 
157 		final List<String> serverOptions = new ArrayList<>();
158 
159 		private Builder() {
160 		}
161 
162 		/**
163 		 * @param objectId
164 		 *            object id received in a "have" line
165 		 * @return this builder
166 		 */
167 		Builder addPeerHas(ObjectId objectId) {
168 			peerHas.add(objectId);
169 			return this;
170 		}
171 
172 		/**
173 		 * Ref received in "want-ref" line and the object-id it refers to
174 		 *
175 		 * @param refName
176 		 *            reference name
177 		 * @return this builder
178 		 */
179 		Builder addWantedRef(String refName) {
180 			wantedRefs.add(refName);
181 			return this;
182 		}
183 
184 		/**
185 		 * @param clientCapability
186 		 *            capability line sent by the client
187 		 * @return this builder
188 		 */
189 		Builder addClientCapability(String clientCapability) {
190 			clientCapabilities.add(clientCapability);
191 			return this;
192 		}
193 
194 		/**
195 		 * @param wantId
196 		 *            object id received in a "want" line
197 		 * @return this builder
198 		 */
199 		Builder addWantId(ObjectId wantId) {
200 			wantIds.add(wantId);
201 			return this;
202 		}
203 
204 		/**
205 		 * @param shallowOid
206 		 *            object id received in a "shallow" line
207 		 * @return this builder
208 		 */
209 		Builder addClientShallowCommit(ObjectId shallowOid) {
210 			clientShallowCommits.add(shallowOid);
211 			return this;
212 		}
213 
214 		/**
215 		 * @param d
216 		 *            Depth received in a "deepen" line
217 		 * @return this builder
218 		 */
219 		Builder setDepth(int d) {
220 			depth = d;
221 			return this;
222 		}
223 
224 		/**
225 		 * @return depth set in the request (via a "deepen" line). Defaulting to
226 		 *         0 if not set.
227 		 */
228 		int getDepth() {
229 			return depth;
230 		}
231 
232 		/**
233 		 * @return true if there has been at least one "deepen not" line in the
234 		 *         request so far
235 		 */
236 		boolean hasDeepenNotRefs() {
237 			return !deepenNotRefs.isEmpty();
238 		}
239 
240 		/**
241 		 * @param deepenNotRef
242 		 *            reference received in a "deepen not" line
243 		 * @return this builder
244 		 */
245 		Builder addDeepenNotRef(String deepenNotRef) {
246 			deepenNotRefs.add(deepenNotRef);
247 			return this;
248 		}
249 
250 		/**
251 		 * @param value
252 		 *            Unix timestamp received in a "deepen since" line
253 		 * @return this builder
254 		 */
255 		Builder setDeepenSince(int value) {
256 			deepenSince = value;
257 			return this;
258 		}
259 
260 		/**
261 		 * @return shallow since value, sent before in a "deepen since" line. 0
262 		 *         by default.
263 		 */
264 		int getDeepenSince() {
265 			return deepenSince;
266 		}
267 
268 		/**
269 		 * @param filterBlobLim
270 		 *            set in a "filter" line
271 		 * @return this builder
272 		 */
273 		Builder setFilterBlobLimit(long filterBlobLim) {
274 			filterBlobLimit = filterBlobLim;
275 			return this;
276 		}
277 
278 		/**
279 		 * Mark that the "done" line has been received.
280 		 *
281 		 * @return this builder
282 		 */
283 		Builder setDoneReceived() {
284 			doneReceived = true;
285 			return this;
286 		}
287 
288 		/**
289 		 * Value of an agent line received after the command and before the
290 		 * arguments. E.g. "agent=a.b.c/1.0" should set "a.b.c/1.0".
291 		 *
292 		 * @param agentValue
293 		 *            the client-supplied agent capability, without the leading
294 		 *            "agent="
295 		 * @return this builder
296 		 */
297 		Builder setAgent(@Nullable String agentValue) {
298 			agent = agentValue;
299 			return this;
300 		}
301 
302 		/**
303 		 * Records an application-specific option supplied in a server-option
304 		 * line, for later retrieval with
305 		 * {@link FetchV2Request#getServerOptions}.
306 		 *
307 		 * @param value
308 		 *            the client-supplied server-option capability, without
309 		 *            leading "server-option=".
310 		 * @return this builder
311 		 */
312 		Builder addServerOption(@NonNull String value) {
313 			serverOptions.add(value);
314 			return this;
315 		}
316 
317 		/**
318 		 * @return Initialized fetch request
319 		 */
320 		FetchV2Request build() {
321 			return new FetchV2Request(peerHas, wantedRefs, wantIds,
322 					clientShallowCommits, deepenSince, deepenNotRefs,
323 					depth, filterBlobLimit, doneReceived, clientCapabilities,
324 					agent, Collections.unmodifiableList(serverOptions));
325 		}
326 	}
327 }