View Javadoc
1   /*
2    * Copyright (C) 2010, 2013 Google Inc. 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  
11  package org.eclipse.jgit.lib;
12  
13  import static java.util.stream.Collectors.toList;
14  import static java.util.stream.Collectors.toSet;
15  
16  import java.io.IOException;
17  import java.util.ArrayList;
18  import java.util.Collection;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  import org.eclipse.jgit.annotations.NonNull;
25  import org.eclipse.jgit.annotations.Nullable;
26  
27  /**
28   * Abstraction of name to {@link org.eclipse.jgit.lib.ObjectId} mapping.
29   * <p>
30   * A reference database stores a mapping of reference names to
31   * {@link org.eclipse.jgit.lib.ObjectId}. Every
32   * {@link org.eclipse.jgit.lib.Repository} has a single reference database,
33   * mapping names to the tips of the object graph contained by the
34   * {@link org.eclipse.jgit.lib.ObjectDatabase}.
35   */
36  public abstract class RefDatabase {
37  	/**
38  	 * Order of prefixes to search when using non-absolute references.
39  	 * <p>
40  	 * {@link #findRef(String)} takes this search space into consideration
41  	 * when locating a reference by name. The first entry in the path is
42  	 * always {@code ""}, ensuring that absolute references are resolved
43  	 * without further mangling.
44  	 */
45  	protected static final String[] SEARCH_PATH = { "", //$NON-NLS-1$
46  			Constants.R_REFS, //
47  			Constants.R_TAGS, //
48  			Constants.R_HEADS, //
49  			Constants.R_REMOTES //
50  	};
51  
52  	/**
53  	 * Maximum number of times a {@link SymbolicRef} can be traversed.
54  	 * <p>
55  	 * If the reference is nested deeper than this depth, the implementation
56  	 * should either fail, or at least claim the reference does not exist.
57  	 *
58  	 * @since 4.2
59  	 */
60  	public static final int MAX_SYMBOLIC_REF_DEPTH = 5;
61  
62  	/**
63  	 * Magic value for {@link #getRefsByPrefix(String)} to return all
64  	 * references.
65  	 */
66  	public static final String ALL = "";//$NON-NLS-1$
67  
68  	/**
69  	 * Initialize a new reference database at this location.
70  	 *
71  	 * @throws java.io.IOException
72  	 *             the database could not be created.
73  	 */
74  	public abstract void create() throws IOException;
75  
76  	/**
77  	 * Close any resources held by this database.
78  	 */
79  	public abstract void close();
80  
81  	/**
82  	 * With versioning, each reference has a version number that increases on
83  	 * update. See {@link Ref#getUpdateIndex()}.
84  	 *
85  	 * @implSpec This method returns false by default. Implementations
86  	 *           supporting versioning must override it to return true.
87  	 * @return true if the implementation assigns update indices to references.
88  	 * @since 5.3
89  	 */
90  	public boolean hasVersioning() {
91  		return false;
92  	}
93  
94  	/**
95  	 * Determine if a proposed reference name overlaps with an existing one.
96  	 * <p>
97  	 * Reference names use '/' as a component separator, and may be stored in a
98  	 * hierarchical storage such as a directory on the local filesystem.
99  	 * <p>
100 	 * If the reference "refs/heads/foo" exists then "refs/heads/foo/bar" must
101 	 * not exist, as a reference cannot have a value and also be a container for
102 	 * other references at the same time.
103 	 * <p>
104 	 * If the reference "refs/heads/foo/bar" exists than the reference
105 	 * "refs/heads/foo" cannot exist, for the same reason.
106 	 *
107 	 * @param name
108 	 *            proposed name.
109 	 * @return true if the name overlaps with an existing reference; false if
110 	 *         using this name right now would be safe.
111 	 * @throws java.io.IOException
112 	 *             the database could not be read to check for conflicts.
113 	 * @see #getConflictingNames(String)
114 	 */
115 	public abstract boolean isNameConflicting(String name) throws IOException;
116 
117 	/**
118 	 * Determine if a proposed reference cannot coexist with existing ones. If
119 	 * the passed name already exists, it's not considered a conflict.
120 	 *
121 	 * @param name
122 	 *            proposed name to check for conflicts against
123 	 * @return a collection of full names of existing refs which would conflict
124 	 *         with the passed ref name; empty collection when there are no
125 	 *         conflicts
126 	 * @throws java.io.IOException
127 	 * @since 2.3
128 	 * @see #isNameConflicting(String)
129 	 */
130 	@NonNull
131 	public Collection<String> getConflictingNames(String name)
132 			throws IOException {
133 		Map<String, Ref> allRefs = getRefs(ALL);
134 		// Cannot be nested within an existing reference.
135 		int lastSlash = name.lastIndexOf('/');
136 		while (0 < lastSlash) {
137 			String needle = name.substring(0, lastSlash);
138 			if (allRefs.containsKey(needle))
139 				return Collections.singletonList(needle);
140 			lastSlash = name.lastIndexOf('/', lastSlash - 1);
141 		}
142 
143 		List<String> conflicting = new ArrayList<>();
144 		// Cannot be the container of an existing reference.
145 		String prefix = name + '/';
146 		for (String existing : allRefs.keySet())
147 			if (existing.startsWith(prefix))
148 				conflicting.add(existing);
149 
150 		return conflicting;
151 	}
152 
153 	/**
154 	 * Create a new update command to create, modify or delete a reference.
155 	 *
156 	 * @param name
157 	 *            the name of the reference.
158 	 * @param detach
159 	 *            if {@code true} and {@code name} is currently a
160 	 *            {@link org.eclipse.jgit.lib.SymbolicRef}, the update will
161 	 *            replace it with an {@link org.eclipse.jgit.lib.ObjectIdRef}.
162 	 *            Otherwise, the update will recursively traverse
163 	 *            {@link org.eclipse.jgit.lib.SymbolicRef}s and operate on the
164 	 *            leaf {@link org.eclipse.jgit.lib.ObjectIdRef}.
165 	 * @return a new update for the requested name; never null.
166 	 * @throws java.io.IOException
167 	 *             the reference space cannot be accessed.
168 	 */
169 	@NonNull
170 	public abstract RefUpdate newUpdate(String name, boolean detach)
171 			throws IOException;
172 
173 	/**
174 	 * Create a new update command to rename a reference.
175 	 *
176 	 * @param fromName
177 	 *            name of reference to rename from
178 	 * @param toName
179 	 *            name of reference to rename to
180 	 * @return an update command that knows how to rename a branch to another.
181 	 * @throws java.io.IOException
182 	 *             the reference space cannot be accessed.
183 	 */
184 	@NonNull
185 	public abstract RefRename newRename(String fromName, String toName)
186 			throws IOException;
187 
188 	/**
189 	 * Create a new batch update to attempt on this database.
190 	 * <p>
191 	 * The default implementation performs a sequential update of each command.
192 	 *
193 	 * @return a new batch update object.
194 	 */
195 	@NonNull
196 	public BatchRefUpdate newBatchUpdate() {
197 		return new BatchRefUpdate(this);
198 	}
199 
200 	/**
201 	 * Whether the database is capable of performing batch updates as atomic
202 	 * transactions.
203 	 * <p>
204 	 * If true, by default {@link org.eclipse.jgit.lib.BatchRefUpdate} instances
205 	 * will perform updates atomically, meaning either all updates will succeed,
206 	 * or all updates will fail. It is still possible to turn off this behavior
207 	 * on a per-batch basis by calling {@code update.setAtomic(false)}.
208 	 * <p>
209 	 * If false, {@link org.eclipse.jgit.lib.BatchRefUpdate} instances will
210 	 * never perform updates atomically, and calling
211 	 * {@code update.setAtomic(true)} will cause the entire batch to fail with
212 	 * {@code REJECTED_OTHER_REASON}.
213 	 * <p>
214 	 * This definition of atomicity is stronger than what is provided by
215 	 * {@link org.eclipse.jgit.transport.ReceivePack}. {@code ReceivePack} will
216 	 * attempt to reject all commands if it knows in advance some commands may
217 	 * fail, even if the storage layer does not support atomic transactions.
218 	 * Here, atomicity applies even in the case of unforeseeable errors.
219 	 *
220 	 * @return whether transactions are atomic by default.
221 	 * @since 3.6
222 	 */
223 	public boolean performsAtomicTransactions() {
224 		return false;
225 	}
226 
227 	/**
228 	 * Compatibility synonym for {@link #findRef(String)}.
229 	 *
230 	 * @param name
231 	 *            the name of the reference. May be a short name which must be
232 	 *            searched for using the standard {@link #SEARCH_PATH}.
233 	 * @return the reference (if it exists); else {@code null}.
234 	 * @throws IOException
235 	 *             the reference space cannot be accessed.
236 	 * @deprecated Use {@link #findRef(String)} instead.
237 	 */
238 	@Deprecated
239 	@Nullable
240 	public final Ref getRef(String name) throws IOException {
241 		return findRef(name);
242 	}
243 
244 	/**
245 	 * Read a single reference.
246 	 * <p>
247 	 * Aside from taking advantage of {@link #SEARCH_PATH}, this method may be
248 	 * able to more quickly resolve a single reference name than obtaining the
249 	 * complete namespace by {@code getRefs(ALL).get(name)}.
250 	 * <p>
251 	 * To read a specific reference without using @{link #SEARCH_PATH}, see
252 	 * {@link #exactRef(String)}.
253 	 *
254 	 * @param name
255 	 *            the name of the reference. May be a short name which must be
256 	 *            searched for using the standard {@link #SEARCH_PATH}.
257 	 * @return the reference (if it exists); else {@code null}.
258 	 * @throws java.io.IOException
259 	 *             the reference space cannot be accessed.
260 	 * @since 5.3
261 	 */
262 	@Nullable
263 	public final Ref findRef(String name) throws IOException {
264 		String[] names = new String[SEARCH_PATH.length];
265 		for (int i = 0; i < SEARCH_PATH.length; i++) {
266 			names[i] = SEARCH_PATH[i] + name;
267 		}
268 		return firstExactRef(names);
269 	}
270 
271 	/**
272 	 * Read a single reference.
273 	 * <p>
274 	 * Unlike {@link #findRef}, this method expects an unshortened reference
275 	 * name and does not search using the standard {@link #SEARCH_PATH}.
276 	 *
277 	 * @param name
278 	 *             the unabbreviated name of the reference.
279 	 * @return the reference (if it exists); else {@code null}.
280 	 * @throws java.io.IOException
281 	 *             the reference space cannot be accessed.
282 	 * @since 4.1
283 	 */
284 	@Nullable
285 	public abstract Ref exactRef(String name) throws IOException;
286 
287 	/**
288 	 * Read the specified references.
289 	 * <p>
290 	 * This method expects a list of unshortened reference names and returns
291 	 * a map from reference names to refs.  Any named references that do not
292 	 * exist will not be included in the returned map.
293 	 *
294 	 * @param refs
295 	 *             the unabbreviated names of references to look up.
296 	 * @return modifiable map describing any refs that exist among the ref
297 	 *         ref names supplied. The map can be an unsorted map.
298 	 * @throws java.io.IOException
299 	 *             the reference space cannot be accessed.
300 	 * @since 4.1
301 	 */
302 	@NonNull
303 	public Map<String, Ref> exactRef(String... refs) throws IOException {
304 		Map<String, Ref> result = new HashMap<>(refs.length);
305 		for (String name : refs) {
306 			Ref ref = exactRef(name);
307 			if (ref != null) {
308 				result.put(name, ref);
309 			}
310 		}
311 		return result;
312 	}
313 
314 	/**
315 	 * Find the first named reference.
316 	 * <p>
317 	 * This method expects a list of unshortened reference names and returns
318 	 * the first that exists.
319 	 *
320 	 * @param refs
321 	 *             the unabbreviated names of references to look up.
322 	 * @return the first named reference that exists (if any); else {@code null}.
323 	 * @throws java.io.IOException
324 	 *             the reference space cannot be accessed.
325 	 * @since 4.1
326 	 */
327 	@Nullable
328 	public Ref firstExactRef(String... refs) throws IOException {
329 		for (String name : refs) {
330 			Ref ref = exactRef(name);
331 			if (ref != null) {
332 				return ref;
333 			}
334 		}
335 		return null;
336 	}
337 
338 	/**
339 	 * Returns all refs.
340 	 * <p>
341 	 * This includes {@code HEAD}, branches under {@code ref/heads/}, tags
342 	 * under {@code refs/tags/}, etc. It does not include pseudo-refs like
343 	 * {@code FETCH_HEAD}; for those, see {@link #getAdditionalRefs}.
344 	 * <p>
345 	 * Symbolic references to a non-existent ref (for example,
346 	 * {@code HEAD} pointing to a branch yet to be born) are not included.
347 	 * <p>
348 	 * Callers interested in only a portion of the ref hierarchy can call
349 	 * {@link #getRefsByPrefix} instead.
350 	 *
351 	 * @return immutable list of all refs.
352 	 * @throws java.io.IOException
353 	 *             the reference space cannot be accessed.
354 	 * @since 5.0
355 	 */
356 	@NonNull
357 	public List<Ref> getRefs() throws IOException {
358 		return getRefsByPrefix(ALL);
359 	}
360 
361 	/**
362 	 * Get a section of the reference namespace.
363 	 *
364 	 * @param prefix
365 	 *            prefix to search the namespace with; must end with {@code /}.
366 	 *            If the empty string ({@link #ALL}), obtain a complete snapshot
367 	 *            of all references.
368 	 * @return modifiable map that is a complete snapshot of the current
369 	 *         reference namespace, with {@code prefix} removed from the start
370 	 *         of each key. The map can be an unsorted map.
371 	 * @throws java.io.IOException
372 	 *             the reference space cannot be accessed.
373 	 * @deprecated use {@link #getRefsByPrefix} instead
374 	 */
375 	@NonNull
376 	@Deprecated
377 	public abstract Map<String, Ref> getRefs(String prefix) throws IOException;
378 
379 	/**
380 	 * Returns refs whose names start with a given prefix.
381 	 * <p>
382 	 * The default implementation uses {@link #getRefs(String)}. Implementors of
383 	 * {@link RefDatabase} should override this method directly if a better
384 	 * implementation is possible.
385 	 *
386 	 * @param prefix string that names of refs should start with; may be
387 	 *             empty (to return all refs).
388 	 * @return immutable list of refs whose names start with {@code prefix}.
389 	 * @throws java.io.IOException
390 	 *             the reference space cannot be accessed.
391 	 * @since 5.0
392 	 */
393 	@NonNull
394 	public List<Ref> getRefsByPrefix(String prefix) throws IOException {
395 		Map<String, Ref> coarseRefs;
396 		int lastSlash = prefix.lastIndexOf('/');
397 		if (lastSlash == -1) {
398 			coarseRefs = getRefs(ALL);
399 		} else {
400 			coarseRefs = getRefs(prefix.substring(0, lastSlash + 1));
401 		}
402 
403 		List<Ref> result;
404 		if (lastSlash + 1 == prefix.length()) {
405 			result = coarseRefs.values().stream().collect(toList());
406 		} else {
407 			String p = prefix.substring(lastSlash + 1);
408 			result = coarseRefs.entrySet().stream()
409 					.filter(e -> e.getKey().startsWith(p))
410 					.map(e -> e.getValue())
411 					.collect(toList());
412 		}
413 		return Collections.unmodifiableList(result);
414 	}
415 
416 	/**
417 	 * Returns refs whose names start with one of the given prefixes.
418 	 * <p>
419 	 * The default implementation uses {@link #getRefsByPrefix(String)}.
420 	 * Implementors of {@link RefDatabase} should override this method directly
421 	 * if a better implementation is possible.
422 	 *
423 	 * @param prefixes
424 	 *            strings that names of refs should start with.
425 	 * @return immutable list of refs whose names start with one of
426 	 *         {@code prefixes}. Refs can be unsorted and may contain duplicates
427 	 *         if the prefixes overlap.
428 	 * @throws java.io.IOException
429 	 *             the reference space cannot be accessed.
430 	 * @since 5.2
431 	 */
432 	@NonNull
433 	public List<Ref> getRefsByPrefix(String... prefixes) throws IOException {
434 		List<Ref> result = new ArrayList<>();
435 		for (String prefix : prefixes) {
436 			result.addAll(getRefsByPrefix(prefix));
437 		}
438 		return Collections.unmodifiableList(result);
439 	}
440 
441 
442 	/**
443 	 * Returns all refs that resolve directly to the given {@link ObjectId}.
444 	 * Includes peeled {@link ObjectId}s. This is the inverse lookup of
445 	 * {@link #exactRef(String...)}.
446 	 *
447 	 * <p>
448 	 * The default implementation uses a linear scan. Implementors of
449 	 * {@link RefDatabase} should override this method directly if a better
450 	 * implementation is possible.
451 	 *
452 	 * @param id
453 	 *            {@link ObjectId} to resolve
454 	 * @return a {@link Set} of {@link Ref}s whose tips point to the provided
455 	 *         id.
456 	 * @throws java.io.IOException
457 	 *             the reference space cannot be accessed.
458 	 * @since 5.4
459 	 */
460 	@NonNull
461 	public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
462 		return getRefs().stream().filter(r -> id.equals(r.getObjectId())
463 				|| id.equals(r.getPeeledObjectId())).collect(toSet());
464 	}
465 
466 	/**
467 	 * If the ref database does not support fast inverse queries, it may
468 	 * be advantageous to build a complete SHA1 to ref map in advance for
469 	 * multiple uses. To let applications decide on this decision,
470 	 * this function indicates whether the inverse map is available.
471 	 *
472 	 * @return whether this RefDatabase supports fast inverse ref queries.
473 	 * @throws IOException on I/O problems.
474 	 * @since 5.6
475 	 */
476 	public boolean hasFastTipsWithSha1() throws IOException {
477 		return false;
478 	}
479 
480 	/**
481 	 * Check if any refs exist in the ref database.
482 	 * <p>
483 	 * This uses the same definition of refs as {@link #getRefs()}. In
484 	 * particular, returns {@code false} in a new repository with no refs
485 	 * under {@code refs/} and {@code HEAD} pointing to a branch yet to be
486 	 * born, and returns {@code true} in a repository with no refs under
487 	 * {@code refs/} and a detached {@code HEAD} pointing to history.
488 	 *
489 	 * @return true if the database has refs.
490 	 * @throws java.io.IOException
491 	 *             the reference space cannot be accessed.
492 	 * @since 5.0
493 	 */
494 	public boolean hasRefs() throws IOException {
495 		return !getRefs().isEmpty();
496 	}
497 
498 	/**
499 	 * Get the additional reference-like entities from the repository.
500 	 * <p>
501 	 * The result list includes non-ref items such as MERGE_HEAD and
502 	 * FETCH_RESULT cast to be refs. The names of these refs are not returned by
503 	 * <code>getRefs()</code> but are accepted by {@link #findRef(String)}
504 	 * and {@link #exactRef(String)}.
505 	 *
506 	 * @return a list of additional refs
507 	 * @throws java.io.IOException
508 	 *             the reference space cannot be accessed.
509 	 */
510 	@NonNull
511 	public abstract List<Ref> getAdditionalRefs() throws IOException;
512 
513 	/**
514 	 * Peel a possibly unpeeled reference by traversing the annotated tags.
515 	 * <p>
516 	 * If the reference cannot be peeled (as it does not refer to an annotated
517 	 * tag) the peeled id stays null, but
518 	 * {@link org.eclipse.jgit.lib.Ref#isPeeled()} will be true.
519 	 * <p>
520 	 * Implementors should check {@link org.eclipse.jgit.lib.Ref#isPeeled()}
521 	 * before performing any additional work effort.
522 	 *
523 	 * @param ref
524 	 *            The reference to peel
525 	 * @return {@code ref} if {@code ref.isPeeled()} is true; otherwise a new
526 	 *         Ref object representing the same data as Ref, but isPeeled() will
527 	 *         be true and getPeeledObjectId() will contain the peeled object
528 	 *         (or {@code null}).
529 	 * @throws java.io.IOException
530 	 *             the reference space or object space cannot be accessed.
531 	 */
532 	@NonNull
533 	public abstract Ref" href="../../../../org/eclipse/jgit/lib/Ref.html#Ref">Ref peel(Ref ref) throws IOException;
534 
535 	/**
536 	 * Triggers a refresh of all internal data structures.
537 	 * <p>
538 	 * In case the RefDatabase implementation has internal caches this method
539 	 * will trigger that all these caches are cleared.
540 	 * <p>
541 	 * Implementors should overwrite this method if they use any kind of caches.
542 	 */
543 	public void refresh() {
544 		// nothing
545 	}
546 
547 	/**
548 	 * Try to find the specified name in the ref map using {@link #SEARCH_PATH}.
549 	 *
550 	 * @param map
551 	 *            map of refs to search within. Names should be fully qualified,
552 	 *            e.g. "refs/heads/master".
553 	 * @param name
554 	 *            short name of ref to find, e.g. "master" to find
555 	 *            "refs/heads/master" in map.
556 	 * @return The first ref matching the name, or {@code null} if not found.
557 	 * @since 3.4
558 	 */
559 	@Nullable
560 	public static Ref findRef(Map<String, Ref> map, String name) {
561 		for (String prefix : SEARCH_PATH) {
562 			String fullname = prefix + name;
563 			Ref ref = map.get(fullname);
564 			if (ref != null)
565 				return ref;
566 		}
567 		return null;
568 	}
569 }