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 java.util.ArrayList;
46  import java.util.HashSet;
47  import java.util.List;
48  import java.util.Map;
49  import java.util.Set;
50  import java.util.TreeMap;
51  
52  import org.eclipse.jgit.annotations.NonNull;
53  import org.eclipse.jgit.lib.ObjectId;
54  
55  /**
56   * fetch protocol v2 request.
57   *
58   * <p>
59   * This is used as an input to {@link ProtocolV2Hook}.
60   *
61   * @since 5.1
62   */
63  public final class FetchV2Request {
64  	private final List<ObjectId> peerHas;
65  
66  	private final TreeMap<String, ObjectId> wantedRefs;
67  
68  	private final Set<ObjectId> wantsIds;
69  
70  	private final Set<ObjectId> clientShallowCommits;
71  
72  	private final int deepenSince;
73  
74  	private final List<String> deepenNotRefs;
75  
76  	private final int depth;
77  
78  	private final long filterBlobLimit;
79  
80  	private final Set<String> options;
81  
82  	private final boolean doneReceived;
83  
84  	private FetchV2Request(List<ObjectId> peerHas,
85  			TreeMap<String, ObjectId> wantedRefs, Set<ObjectId> wantsIds,
86  			Set<ObjectId> clientShallowCommits, int deepenSince,
87  			List<String> deepenNotRefs, int depth, long filterBlobLimit,
88  			boolean doneReceived, Set<String> options) {
89  		this.peerHas = peerHas;
90  		this.wantedRefs = wantedRefs;
91  		this.wantsIds = wantsIds;
92  		this.clientShallowCommits = clientShallowCommits;
93  		this.deepenSince = deepenSince;
94  		this.deepenNotRefs = deepenNotRefs;
95  		this.depth = depth;
96  		this.filterBlobLimit = filterBlobLimit;
97  		this.doneReceived = doneReceived;
98  		this.options = options;
99  	}
100 
101 	/**
102 	 * @return object ids in the "have" lines of the request
103 	 */
104 	@NonNull
105 	List<ObjectId> getPeerHas() {
106 		return this.peerHas;
107 	}
108 
109 	/**
110 	 * @return list of references in the "want-ref" lines of the request
111 	 */
112 	@NonNull
113 	Map<String, ObjectId> getWantedRefs() {
114 		return this.wantedRefs;
115 	}
116 
117 	/**
118 	 * @return object ids in the "want" (and "want-ref") lines of the request
119 	 */
120 	@NonNull
121 	Set<ObjectId> getWantsIds() {
122 		return wantsIds;
123 	}
124 
125 	/**
126 	 * Shallow commits the client already has.
127 	 *
128 	 * These are sent by the client in "shallow" request lines.
129 	 *
130 	 * @return set of commits the client has declared as shallow.
131 	 */
132 	@NonNull
133 	Set<ObjectId> getClientShallowCommits() {
134 		return clientShallowCommits;
135 	}
136 
137 	/**
138 	 * The value in a "deepen-since" line in the request, indicating the
139 	 * timestamp where to stop fetching/cloning.
140 	 *
141 	 * @return timestamp in seconds since the epoch, where to stop the shallow
142 	 *         fetch/clone. Defaults to 0 if not set in the request.
143 	 */
144 	int getDeepenSince() {
145 		return deepenSince;
146 	}
147 
148 	/**
149 	 * @return the refs in "deepen-not" lines in the request.
150 	 */
151 	@NonNull
152 	List<String> getDeepenNotRefs() {
153 		return deepenNotRefs;
154 	}
155 
156 	/**
157 	 * @return the depth set in a "deepen" line. 0 by default.
158 	 */
159 	int getDepth() {
160 		return depth;
161 	}
162 
163 	/**
164 	 * @return the blob limit set in a "filter" line (-1 if not set)
165 	 */
166 	long getFilterBlobLimit() {
167 		return filterBlobLimit;
168 	}
169 
170 	/**
171 	 * @return true if the request had a "done" line
172 	 */
173 	boolean wasDoneReceived() {
174 		return doneReceived;
175 	}
176 
177 	/**
178 	 * Options that tune the expected response from the server, like
179 	 * "thin-pack", "no-progress" or "ofs-delta"
180 	 *
181 	 * These are options listed and well-defined in the git protocol
182 	 * specification
183 	 *
184 	 * @return options found in the request lines
185 	 */
186 	@NonNull
187 	Set<String> getOptions() {
188 		return options;
189 	}
190 
191 	/** @return A builder of {@link FetchV2Request}. */
192 	static Builder builder() {
193 		return new Builder();
194 	}
195 
196 
197 	/** A builder for {@link FetchV2Request}. */
198 	static final class Builder {
199 		List<ObjectId> peerHas = new ArrayList<>();
200 
201 		TreeMap<String, ObjectId> wantedRefs = new TreeMap<>();
202 
203 		Set<ObjectId> wantsIds = new HashSet<>();
204 
205 		Set<ObjectId> clientShallowCommits = new HashSet<>();
206 
207 		List<String> deepenNotRefs = new ArrayList<>();
208 
209 		Set<String> options = new HashSet<>();
210 
211 		int depth;
212 
213 		int deepenSince;
214 
215 		long filterBlobLimit = -1;
216 
217 		boolean doneReceived;
218 
219 		private Builder() {
220 		}
221 
222 		/**
223 		 * @param objectId
224 		 *            from a "have" line in a fetch request
225 		 * @return the builder
226 		 */
227 		Builder addPeerHas(ObjectId objectId) {
228 			peerHas.add(objectId);
229 			return this;
230 		}
231 
232 		/**
233 		 * From a "want-ref" line in a fetch request
234 		 *
235 		 * @param refName
236 		 *            reference name
237 		 * @param oid
238 		 *            object id
239 		 * @return the builder
240 		 */
241 		Builder addWantedRef(String refName, ObjectId oid) {
242 			wantedRefs.put(refName, oid);
243 			return this;
244 		}
245 
246 		/**
247 		 * @param option
248 		 *            fetch request lines acting as options
249 		 * @return the builder
250 		 */
251 		Builder addOption(String option) {
252 			options.add(option);
253 			return this;
254 		}
255 
256 		/**
257 		 * @param objectId
258 		 *            from a "want" line in a fetch request
259 		 * @return the builder
260 		 */
261 		Builder addWantsIds(ObjectId objectId) {
262 			wantsIds.add(objectId);
263 			return this;
264 		}
265 
266 		/**
267 		 * @param shallowOid
268 		 *            from a "shallow" line in the fetch request
269 		 * @return the builder
270 		 */
271 		Builder addClientShallowCommit(ObjectId shallowOid) {
272 			this.clientShallowCommits.add(shallowOid);
273 			return this;
274 		}
275 
276 		/**
277 		 * @param d
278 		 *            from a "deepen" line in the fetch request
279 		 * @return the builder
280 		 */
281 		Builder setDepth(int d) {
282 			this.depth = d;
283 			return this;
284 		}
285 
286 		/**
287 		 * @return depth set in the request (via a "deepen" line). Defaulting to
288 		 *         0 if not set.
289 		 */
290 		int getDepth() {
291 			return this.depth;
292 		}
293 
294 		/**
295 		 * @return if there has been any "deepen not" line in the request
296 		 */
297 		boolean hasDeepenNotRefs() {
298 			return !deepenNotRefs.isEmpty();
299 		}
300 
301 		/**
302 		 * @param deepenNotRef reference in a "deepen not" line
303 		 * @return the builder
304 		 */
305 		Builder addDeepenNotRef(String deepenNotRef) {
306 			this.deepenNotRefs.add(deepenNotRef);
307 			return this;
308 		}
309 
310 		/**
311 		 * @param value
312 		 *            Unix timestamp received in a "deepen since" line
313 		 * @return the builder
314 		 */
315 		Builder setDeepenSince(int value) {
316 			this.deepenSince = value;
317 			return this;
318 		}
319 
320 		/**
321 		 * @return shallow since value, sent before in a "deepen since" line. 0
322 		 *         by default.
323 		 */
324 		int getDeepenSince() {
325 			return this.deepenSince;
326 		}
327 
328 		/**
329 		 * @param filterBlobLimit
330 		 *            set in a "filter" line
331 		 * @return the builder
332 		 */
333 		Builder setFilterBlobLimit(long filterBlobLimit) {
334 			this.filterBlobLimit = filterBlobLimit;
335 			return this;
336 		}
337 
338 		/**
339 		 * Mark that the "done" line has been received.
340 		 *
341 		 * @return the builder
342 		 */
343 		Builder setDoneReceived() {
344 			this.doneReceived = true;
345 			return this;
346 		}
347 		/**
348 		 * @return Initialized fetch request
349 		 */
350 		FetchV2Request build() {
351 			return new FetchV2Request(peerHas, wantedRefs, wantsIds,
352 					clientShallowCommits, deepenSince, deepenNotRefs,
353 					depth, filterBlobLimit, doneReceived, options);
354 		}
355 	}
356 }