You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ObjectInserter.java 10KB

Merging Git notes Merging Git notes branches has several differences from merging "normal" branches. Although Git notes are initially stored as one flat tree the tree may fanout when the number of notes becomes too large for efficient access. In this case the first two hex digits of the note name will be used as a subdirectory name and the rest 38 hex digits as the file name under that directory. Similarly, when number of notes decreases a fanout tree may collapse back into a flat tree. The Git notes merge algorithm must take into account possibly different tree structures in different note branches and must properly match them against each other. Any conflict on a Git note is, by default, resolved by concatenating the two conflicting versions of the note. A delete-edit conflict is, by default, resolved by keeping the edit version. The note merge logic is pluggable and the caller may provide custom note merger that will perform different merging strategy. Additionally, it is possible to have non-note entries inside a notes tree. The merge algorithm must also take this fact into account and will try to merge such non-note entries. However, in case of any merge conflicts the merge operation will fail. Git notes merge algorithm is currently not trying to do content merge of non-note entries. Thanks to Shawn Pearce for patiently answering my questions related to this topic, giving hints and providing code snippets. Change-Id: I3b2335c76c766fd7ea25752e54087f9b19d69c88 Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
  3. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  4. * Copyright (C) 2009, Google Inc.
  5. * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
  6. * and other copyright owners as documented in the project's IP log.
  7. *
  8. * This program and the accompanying materials are made available
  9. * under the terms of the Eclipse Distribution License v1.0 which
  10. * accompanies this distribution, is reproduced below, and is
  11. * available at http://www.eclipse.org/org/documents/edl-v10.php
  12. *
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or
  16. * without modification, are permitted provided that the following
  17. * conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. *
  22. * - Redistributions in binary form must reproduce the above
  23. * copyright notice, this list of conditions and the following
  24. * disclaimer in the documentation and/or other materials provided
  25. * with the distribution.
  26. *
  27. * - Neither the name of the Eclipse Foundation, Inc. nor the
  28. * names of its contributors may be used to endorse or promote
  29. * products derived from this software without specific prior
  30. * written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  33. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  34. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  35. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  37. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  39. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  40. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  41. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  42. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  43. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  44. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. */
  46. package org.eclipse.jgit.lib;
  47. import java.io.ByteArrayInputStream;
  48. import java.io.EOFException;
  49. import java.io.IOException;
  50. import java.io.InputStream;
  51. import java.security.MessageDigest;
  52. import org.eclipse.jgit.transport.PackParser;
  53. /**
  54. * Inserts objects into an existing {@code ObjectDatabase}.
  55. * <p>
  56. * An inserter is not thread-safe. Individual threads should each obtain their
  57. * own unique inserter instance, or must arrange for locking at a higher level
  58. * to ensure the inserter is in use by no more than one thread at a time.
  59. * <p>
  60. * Objects written by an inserter may not be immediately visible for reading
  61. * after the insert method completes. Callers must invoke either
  62. * {@link #release()} or {@link #flush()} prior to updating references or
  63. * otherwise making the returned ObjectIds visible to other code.
  64. */
  65. public abstract class ObjectInserter {
  66. /** An inserter that can be used for formatting and id generation only. */
  67. public static class Formatter extends ObjectInserter {
  68. @Override
  69. public ObjectId insert(int objectType, long length, InputStream in)
  70. throws IOException {
  71. throw new UnsupportedOperationException();
  72. }
  73. @Override
  74. public PackParser newPackParser(InputStream in) throws IOException {
  75. throw new UnsupportedOperationException();
  76. }
  77. @Override
  78. public void flush() throws IOException {
  79. // Do nothing.
  80. }
  81. @Override
  82. public void release() {
  83. // Do nothing.
  84. }
  85. }
  86. /** Digest to compute the name of an object. */
  87. private final MessageDigest digest;
  88. /** Temporary working buffer for streaming data through. */
  89. private byte[] tempBuffer;
  90. /** Create a new inserter for a database. */
  91. protected ObjectInserter() {
  92. digest = Constants.newMessageDigest();
  93. }
  94. /** @return a temporary byte array for use by the caller. */
  95. protected byte[] buffer() {
  96. if (tempBuffer == null)
  97. tempBuffer = new byte[8192];
  98. return tempBuffer;
  99. }
  100. /** @return digest to help compute an ObjectId */
  101. protected MessageDigest digest() {
  102. digest.reset();
  103. return digest;
  104. }
  105. /**
  106. * Compute the name of an object, without inserting it.
  107. *
  108. * @param type
  109. * type code of the object to store.
  110. * @param data
  111. * complete content of the object.
  112. * @return the name of the object.
  113. */
  114. public ObjectId idFor(int type, byte[] data) {
  115. return idFor(type, data, 0, data.length);
  116. }
  117. /**
  118. * Compute the name of an object, without inserting it.
  119. *
  120. * @param type
  121. * type code of the object to store.
  122. * @param data
  123. * complete content of the object.
  124. * @param off
  125. * first position within {@code data}.
  126. * @param len
  127. * number of bytes to copy from {@code data}.
  128. * @return the name of the object.
  129. */
  130. public ObjectId idFor(int type, byte[] data, int off, int len) {
  131. MessageDigest md = digest();
  132. md.update(Constants.encodedTypeString(type));
  133. md.update((byte) ' ');
  134. md.update(Constants.encodeASCII(len));
  135. md.update((byte) 0);
  136. md.update(data, off, len);
  137. return ObjectId.fromRaw(md.digest());
  138. }
  139. /**
  140. * Compute the name of an object, without inserting it.
  141. *
  142. * @param objectType
  143. * type code of the object to store.
  144. * @param length
  145. * number of bytes to scan from {@code in}.
  146. * @param in
  147. * stream providing the object content. The caller is responsible
  148. * for closing the stream.
  149. * @return the name of the object.
  150. * @throws IOException
  151. * the source stream could not be read.
  152. */
  153. public ObjectId idFor(int objectType, long length, InputStream in)
  154. throws IOException {
  155. MessageDigest md = digest();
  156. md.update(Constants.encodedTypeString(objectType));
  157. md.update((byte) ' ');
  158. md.update(Constants.encodeASCII(length));
  159. md.update((byte) 0);
  160. byte[] buf = buffer();
  161. while (length > 0) {
  162. int n = in.read(buf, 0, (int) Math.min(length, buf.length));
  163. if (n < 0)
  164. throw new EOFException("Unexpected end of input");
  165. md.update(buf, 0, n);
  166. length -= n;
  167. }
  168. return ObjectId.fromRaw(md.digest());
  169. }
  170. /**
  171. * Compute the ObjectId for the given tree without inserting it.
  172. *
  173. * @param formatter
  174. * @return the computed ObjectId
  175. */
  176. public ObjectId idFor(TreeFormatter formatter) {
  177. return formatter.computeId(this);
  178. }
  179. /**
  180. * Insert a single tree into the store, returning its unique name.
  181. *
  182. * @param formatter
  183. * the formatter containing the proposed tree's data.
  184. * @return the name of the tree object.
  185. * @throws IOException
  186. * the object could not be stored.
  187. */
  188. public final ObjectId insert(TreeFormatter formatter) throws IOException {
  189. // Delegate to the formatter, as then it can pass the raw internal
  190. // buffer back to this inserter, avoiding unnecessary data copying.
  191. //
  192. return formatter.insertTo(this);
  193. }
  194. /**
  195. * Insert a single commit into the store, returning its unique name.
  196. *
  197. * @param builder
  198. * the builder containing the proposed commit's data.
  199. * @return the name of the commit object.
  200. * @throws IOException
  201. * the object could not be stored.
  202. */
  203. public final ObjectId insert(CommitBuilder builder) throws IOException {
  204. return insert(Constants.OBJ_COMMIT, builder.build());
  205. }
  206. /**
  207. * Insert a single annotated tag into the store, returning its unique name.
  208. *
  209. * @param builder
  210. * the builder containing the proposed tag's data.
  211. * @return the name of the tag object.
  212. * @throws IOException
  213. * the object could not be stored.
  214. */
  215. public final ObjectId insert(TagBuilder builder) throws IOException {
  216. return insert(Constants.OBJ_TAG, builder.build());
  217. }
  218. /**
  219. * Insert a single object into the store, returning its unique name.
  220. *
  221. * @param type
  222. * type code of the object to store.
  223. * @param data
  224. * complete content of the object.
  225. * @return the name of the object.
  226. * @throws IOException
  227. * the object could not be stored.
  228. */
  229. public ObjectId insert(final int type, final byte[] data)
  230. throws IOException {
  231. return insert(type, data, 0, data.length);
  232. }
  233. /**
  234. * Insert a single object into the store, returning its unique name.
  235. *
  236. * @param type
  237. * type code of the object to store.
  238. * @param data
  239. * complete content of the object.
  240. * @param off
  241. * first position within {@code data}.
  242. * @param len
  243. * number of bytes to copy from {@code data}.
  244. * @return the name of the object.
  245. * @throws IOException
  246. * the object could not be stored.
  247. */
  248. public ObjectId insert(int type, byte[] data, int off, int len)
  249. throws IOException {
  250. return insert(type, len, new ByteArrayInputStream(data, off, len));
  251. }
  252. /**
  253. * Insert a single object into the store, returning its unique name.
  254. *
  255. * @param objectType
  256. * type code of the object to store.
  257. * @param length
  258. * number of bytes to copy from {@code in}.
  259. * @param in
  260. * stream providing the object content. The caller is responsible
  261. * for closing the stream.
  262. * @return the name of the object.
  263. * @throws IOException
  264. * the object could not be stored, or the source stream could
  265. * not be read.
  266. */
  267. public abstract ObjectId insert(int objectType, long length, InputStream in)
  268. throws IOException;
  269. /**
  270. * Initialize a parser to read from a pack formatted stream.
  271. *
  272. * @param in
  273. * the input stream. The stream is not closed by the parser, and
  274. * must instead be closed by the caller once parsing is complete.
  275. * @return the pack parser.
  276. * @throws IOException
  277. * the parser instance, which can be configured and then used to
  278. * parse objects into the ObjectDatabase.
  279. */
  280. public abstract PackParser newPackParser(InputStream in) throws IOException;
  281. /**
  282. * Make all inserted objects visible.
  283. * <p>
  284. * The flush may take some period of time to make the objects available to
  285. * other threads.
  286. *
  287. * @throws IOException
  288. * the flush could not be completed; objects inserted thus far
  289. * are in an indeterminate state.
  290. */
  291. public abstract void flush() throws IOException;
  292. /**
  293. * Release any resources used by this inserter.
  294. * <p>
  295. * An inserter that has been released can be used again, but may need to be
  296. * released after the subsequent usage.
  297. */
  298. public abstract void release();
  299. }