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