View Javadoc
1   /*
2    * Copyright (C) 2018, Google LLC. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.transport;
11  
12  import static java.util.Objects.requireNonNull;
13  
14  import java.util.ArrayList;
15  import java.util.Collections;
16  import java.util.HashSet;
17  import java.util.List;
18  import java.util.Set;
19  
20  import org.eclipse.jgit.annotations.NonNull;
21  import org.eclipse.jgit.annotations.Nullable;
22  import org.eclipse.jgit.lib.ObjectId;
23  
24  /**
25   * Fetch request from git protocol v2.
26   *
27   * <p>
28   * This is used as an input to {@link ProtocolV2Hook}.
29   *
30   * @since 5.1
31   */
32  public final class FetchV2Request extends FetchRequest {
33  	private final List<ObjectId> peerHas;
34  
35  	private final List<String> wantedRefs;
36  
37  	private final boolean doneReceived;
38  
39  	private final boolean waitForDone;
40  
41  	@NonNull
42  	private final List<String> serverOptions;
43  
44  	private final boolean sidebandAll;
45  
46  	@NonNull
47  	private final List<String> packfileUriProtocols;
48  
49  	FetchV2Request(@NonNull List<ObjectId> peerHas,
50  			@NonNull List<String> wantedRefs,
51  			@NonNull Set<ObjectId> wantIds,
52  			@NonNull Set<ObjectId> clientShallowCommits, int deepenSince,
53  			@NonNull List<String> deepenNotRefs, int depth,
54  			@NonNull FilterSpec filterSpec,
55  			boolean doneReceived, boolean waitForDone,
56  			@NonNull Set<String> clientCapabilities,
57  			@Nullable String agent, @NonNull List<String> serverOptions,
58  			boolean sidebandAll, @NonNull List<String> packfileUriProtocols) {
59  		super(wantIds, depth, clientShallowCommits, filterSpec,
60  				clientCapabilities, deepenSince,
61  				deepenNotRefs, agent);
62  		this.peerHas = requireNonNull(peerHas);
63  		this.wantedRefs = requireNonNull(wantedRefs);
64  		this.doneReceived = doneReceived;
65  		this.waitForDone = waitForDone;
66  		this.serverOptions = requireNonNull(serverOptions);
67  		this.sidebandAll = sidebandAll;
68  		this.packfileUriProtocols = packfileUriProtocols;
69  	}
70  
71  	/**
72  	 * @return object ids received in the "have" lines
73  	 */
74  	@NonNull
75  	List<ObjectId> getPeerHas() {
76  		return peerHas;
77  	}
78  
79  	/**
80  	 * @return list of references received in "want-ref" lines
81  	 *
82  	 * @since 5.4
83  	 */
84  	@NonNull
85  	public List<String> getWantedRefs() {
86  		return wantedRefs;
87  	}
88  
89  	/**
90  	 * @return true if the request had a "done" line
91  	 */
92  	boolean wasDoneReceived() {
93  		return doneReceived;
94  	}
95  
96  	/**
97  	 * @return true if the request had a "wait-for-done" line
98  	 */
99  	boolean wasWaitForDoneReceived() {
100 		return waitForDone;
101 	}
102 
103 	/**
104 	 * Options received in server-option lines. The caller can choose to	 act on
105 	 * these in an application-specific way
106 	 *
107 	 * @return Immutable list of server options received in the request
108 	 *
109 	 * @since 5.2
110 	 */
111 	@NonNull
112 	public List<String> getServerOptions() {
113 		return serverOptions;
114 	}
115 
116 	/**
117 	 * @return true if "sideband-all" was received
118 	 */
119 	boolean getSidebandAll() {
120 		return sidebandAll;
121 	}
122 
123 	@NonNull
124 	List<String> getPackfileUriProtocols() {
125 		return packfileUriProtocols;
126 	}
127 
128 	/** @return A builder of {@link FetchV2Request}. */
129 	static Builder builder() {
130 		return new Builder();
131 	}
132 
133 	/** A builder for {@link FetchV2Request}. */
134 	static final class Builder {
135 		final List<ObjectId> peerHas = new ArrayList<>();
136 
137 		final List<String> wantedRefs = new ArrayList<>();
138 
139 		final Set<ObjectId> wantIds = new HashSet<>();
140 
141 		final Set<ObjectId> clientShallowCommits = new HashSet<>();
142 
143 		final List<String> deepenNotRefs = new ArrayList<>();
144 
145 		final Set<String> clientCapabilities = new HashSet<>();
146 
147 		int depth;
148 
149 		int deepenSince;
150 
151 		FilterSpec filterSpec = FilterSpec.NO_FILTER;
152 
153 		boolean doneReceived;
154 
155 		boolean waitForDone;
156 
157 		@Nullable
158 		String agent;
159 
160 		final List<String> serverOptions = new ArrayList<>();
161 
162 		boolean sidebandAll;
163 
164 		final List<String> packfileUriProtocols = new ArrayList<>();
165 
166 		private Builder() {
167 		}
168 
169 		/**
170 		 * @param objectId
171 		 *            object id received in a "have" line
172 		 * @return this builder
173 		 */
174 		Builder addPeerHas(ObjectId objectId) {
175 			peerHas.add(objectId);
176 			return this;
177 		}
178 
179 		/**
180 		 * Ref received in "want-ref" line and the object-id it refers to
181 		 *
182 		 * @param refName
183 		 *            reference name
184 		 * @return this builder
185 		 */
186 		Builder addWantedRef(String refName) {
187 			wantedRefs.add(refName);
188 			return this;
189 		}
190 
191 		/**
192 		 * @param clientCapability
193 		 *            capability line sent by the client
194 		 * @return this builder
195 		 */
196 		Builder addClientCapability(String clientCapability) {
197 			clientCapabilities.add(clientCapability);
198 			return this;
199 		}
200 
201 		/**
202 		 * @param wantId
203 		 *            object id received in a "want" line
204 		 * @return this builder
205 		 */
206 		Builder addWantId(ObjectId wantId) {
207 			wantIds.add(wantId);
208 			return this;
209 		}
210 
211 		/**
212 		 * @param shallowOid
213 		 *            object id received in a "shallow" line
214 		 * @return this builder
215 		 */
216 		Builder addClientShallowCommit(ObjectId shallowOid) {
217 			clientShallowCommits.add(shallowOid);
218 			return this;
219 		}
220 
221 		/**
222 		 * @param d
223 		 *            Depth received in a "deepen" line
224 		 * @return this builder
225 		 */
226 		Builder setDepth(int d) {
227 			depth = d;
228 			return this;
229 		}
230 
231 		/**
232 		 * @return depth set in the request (via a "deepen" line). Defaulting to
233 		 *         0 if not set.
234 		 */
235 		int getDepth() {
236 			return depth;
237 		}
238 
239 		/**
240 		 * @return true if there has been at least one "deepen not" line in the
241 		 *         request so far
242 		 */
243 		boolean hasDeepenNotRefs() {
244 			return !deepenNotRefs.isEmpty();
245 		}
246 
247 		/**
248 		 * @param deepenNotRef
249 		 *            reference received in a "deepen not" line
250 		 * @return this builder
251 		 */
252 		Builder addDeepenNotRef(String deepenNotRef) {
253 			deepenNotRefs.add(deepenNotRef);
254 			return this;
255 		}
256 
257 		/**
258 		 * @param value
259 		 *            Unix timestamp received in a "deepen since" line
260 		 * @return this builder
261 		 */
262 		Builder setDeepenSince(int value) {
263 			deepenSince = value;
264 			return this;
265 		}
266 
267 		/**
268 		 * @return shallow since value, sent before in a "deepen since" line. 0
269 		 *         by default.
270 		 */
271 		int getDeepenSince() {
272 			return deepenSince;
273 		}
274 
275 		/**
276 		 * @param filter
277 		 *            spec set in a "filter" line
278 		 * @return this builder
279 		 */
280 		Builder setFilterSpec(@NonNull FilterSpec filter) {
281 			filterSpec = requireNonNull(filter);
282 			return this;
283 		}
284 
285 		/**
286 		 * Mark that the "done" line has been received.
287 		 *
288 		 * @return this builder
289 		 */
290 		Builder setDoneReceived() {
291 			doneReceived = true;
292 			return this;
293 		}
294 
295 		/**
296 		 * Mark that the "wait-for-done" line has been received.
297 		 *
298 		 * @return this builder
299 		 */
300 		Builder setWaitForDone() {
301 			waitForDone = true;
302 			return this;
303 		}
304 
305 		/**
306 		 * Value of an agent line received after the command and before the
307 		 * arguments. E.g. "agent=a.b.c/1.0" should set "a.b.c/1.0".
308 		 *
309 		 * @param agentValue
310 		 *            the client-supplied agent capability, without the leading
311 		 *            "agent="
312 		 * @return this builder
313 		 */
314 		Builder setAgent(@Nullable String agentValue) {
315 			agent = agentValue;
316 			return this;
317 		}
318 
319 		/**
320 		 * Records an application-specific option supplied in a server-option
321 		 * line, for later retrieval with
322 		 * {@link FetchV2Request#getServerOptions}.
323 		 *
324 		 * @param value
325 		 *            the client-supplied server-option capability, without
326 		 *            leading "server-option=".
327 		 * @return this builder
328 		 */
329 		Builder addServerOption(@NonNull String value) {
330 			serverOptions.add(value);
331 			return this;
332 		}
333 
334 		/**
335 		 * @param value true if client sent "sideband-all"
336 		 * @return this builder
337 		 */
338 		Builder setSidebandAll(boolean value) {
339 			sidebandAll = value;
340 			return this;
341 		}
342 
343 		Builder addPackfileUriProtocol(@NonNull String value) {
344 			packfileUriProtocols.add(value);
345 			return this;
346 		}
347 
348 		/**
349 		 * @return Initialized fetch request
350 		 */
351 		FetchV2Request build() {
352 			return new FetchV2Request(peerHas, wantedRefs, wantIds,
353 					clientShallowCommits, deepenSince, deepenNotRefs,
354 					depth, filterSpec, doneReceived, waitForDone, clientCapabilities,
355 					agent, Collections.unmodifiableList(serverOptions),
356 					sidebandAll,
357 					Collections.unmodifiableList(packfileUriProtocols));
358 		}
359 	}
360 }