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.

IndexTreeWalker.java 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
  3. * Copyright (C) 2007-2009, Robin Rosenberg <robin.rosenberg@dewire.com>
  4. * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
  5. * and other copyright owners as documented in the project's IP log.
  6. *
  7. * This program and the accompanying materials are made available
  8. * under the terms of the Eclipse Distribution License v1.0 which
  9. * accompanies this distribution, is reproduced below, and is
  10. * available at http://www.eclipse.org/org/documents/edl-v10.php
  11. *
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or
  15. * without modification, are permitted provided that the following
  16. * conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials provided
  24. * with the distribution.
  25. *
  26. * - Neither the name of the Eclipse Foundation, Inc. nor the
  27. * names of its contributors may be used to endorse or promote
  28. * products derived from this software without specific prior
  29. * written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  32. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  33. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  36. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  37. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  38. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  39. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  40. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  43. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. package org.eclipse.jgit.lib;
  46. import java.io.File;
  47. import java.io.IOException;
  48. import org.eclipse.jgit.lib.GitIndex.Entry;
  49. /**
  50. * A class for traversing the index and one or two trees.
  51. *
  52. * A visitor is invoked for executing actions, like figuring out how to merge.
  53. */
  54. public class IndexTreeWalker {
  55. private final Tree mainTree;
  56. private final Tree newTree;
  57. private final File root;
  58. private final IndexTreeVisitor visitor;
  59. private boolean threeTrees;
  60. /**
  61. * Construct a walker for the index and one tree.
  62. *
  63. * @param index
  64. * @param tree
  65. * @param root
  66. * @param visitor
  67. */
  68. public IndexTreeWalker(GitIndex index, Tree tree, File root, IndexTreeVisitor visitor) {
  69. this.mainTree = tree;
  70. this.root = root;
  71. this.visitor = visitor;
  72. this.newTree = null;
  73. threeTrees = false;
  74. indexMembers = index.getMembers();
  75. }
  76. /**
  77. * Construct a walker for the index and two trees.
  78. *
  79. * @param index
  80. * @param mainTree
  81. * @param newTree
  82. * @param root
  83. * @param visitor
  84. */
  85. public IndexTreeWalker(GitIndex index, Tree mainTree, Tree newTree, File root, IndexTreeVisitor visitor) {
  86. this.mainTree = mainTree;
  87. this.newTree = newTree;
  88. this.root = root;
  89. this.visitor = visitor;
  90. threeTrees = true;
  91. indexMembers = index.getMembers();
  92. }
  93. Entry[] indexMembers;
  94. int indexCounter = 0;
  95. /**
  96. * Actually walk the index tree
  97. *
  98. * @throws IOException
  99. */
  100. public void walk() throws IOException {
  101. walk(mainTree, newTree);
  102. }
  103. private void walk(Tree tree, Tree auxTree) throws IOException {
  104. TreeIterator mi = new TreeIterator(tree, TreeIterator.Order.POSTORDER);
  105. TreeIterator ai = new TreeIterator(auxTree, TreeIterator.Order.POSTORDER);
  106. TreeEntry m = mi.hasNext() ? mi.next() : null;
  107. TreeEntry a = ai.hasNext() ? ai.next() : null;
  108. int curIndexPos = indexCounter;
  109. Entry i = indexCounter < indexMembers.length ? indexMembers[indexCounter++] : null;
  110. while (m != null || a != null || i != null) {
  111. int cmpma = compare(m, a);
  112. int cmpmi = compare(m, i);
  113. int cmpai = compare(a, i);
  114. TreeEntry pm = cmpma <= 0 && cmpmi <= 0 ? m : null;
  115. TreeEntry pa = cmpma >= 0 && cmpai <= 0 ? a : null;
  116. Entry pi = cmpmi >= 0 && cmpai >= 0 ? i : null;
  117. if (pi != null)
  118. visitEntry(pm, pa, pi);
  119. else
  120. finishVisitTree(pm, pa, curIndexPos);
  121. if (pm != null) m = mi.hasNext() ? mi.next() : null;
  122. if (pa != null) a = ai.hasNext() ? ai.next() : null;
  123. if (pi != null) i = indexCounter < indexMembers.length ? indexMembers[indexCounter++] : null;
  124. }
  125. }
  126. private void visitEntry(TreeEntry t1, TreeEntry t2,
  127. Entry i) throws IOException {
  128. assert t1 != null || t2 != null || i != null : "Needs at least one entry";
  129. assert root != null : "Needs workdir";
  130. if (t1 != null && t1.getParent() == null)
  131. t1 = null;
  132. if (t2 != null && t2.getParent() == null)
  133. t2 = null;
  134. File f = null;
  135. if (i != null)
  136. f = new File(root, i.getName());
  137. else if (t1 != null)
  138. f = new File(root, t1.getFullName());
  139. else if (t2 != null)
  140. f = new File(root, t2.getFullName());
  141. if (t1 != null || t2 != null || i != null)
  142. if (threeTrees)
  143. visitor.visitEntry(t1, t2, i, f);
  144. else
  145. visitor.visitEntry(t1, i, f);
  146. }
  147. private void finishVisitTree(TreeEntry t1, TreeEntry t2, int curIndexPos)
  148. throws IOException {
  149. assert t1 != null || t2 != null : "Needs at least one entry";
  150. assert root != null : "Needs workdir";
  151. if (t1 != null && t1.getParent() == null)
  152. t1 = null;
  153. if (t2 != null && t2.getParent() == null)
  154. t2 = null;
  155. File f = null;
  156. String c= null;
  157. if (t1 != null) {
  158. c = t1.getFullName();
  159. f = new File(root, c);
  160. } else if (t2 != null) {
  161. c = t2.getFullName();
  162. f = new File(root, c);
  163. }
  164. if (t1 instanceof Tree || t2 instanceof Tree)
  165. if (threeTrees)
  166. visitor.finishVisitTree((Tree)t1, (Tree)t2, c);
  167. else
  168. visitor.finishVisitTree((Tree)t1, indexCounter - curIndexPos, c);
  169. else if (t1 != null || t2 != null)
  170. if (threeTrees)
  171. visitor.visitEntry(t1, t2, null, f);
  172. else
  173. visitor.visitEntry(t1, null, f);
  174. }
  175. static boolean lt(TreeEntry h, Entry i) {
  176. return compare(h, i) < 0;
  177. }
  178. static boolean lt(Entry i, TreeEntry t) {
  179. return compare(t, i) > 0;
  180. }
  181. static boolean lt(TreeEntry h, TreeEntry m) {
  182. return compare(h, m) < 0;
  183. }
  184. static boolean eq(TreeEntry t1, TreeEntry t2) {
  185. return compare(t1, t2) == 0;
  186. }
  187. static boolean eq(TreeEntry t1, Entry e) {
  188. return compare(t1, e) == 0;
  189. }
  190. static int compare(TreeEntry t, Entry i) {
  191. if (t == null && i == null)
  192. return 0;
  193. if (t == null)
  194. return 1;
  195. if (i == null)
  196. return -1;
  197. return Tree.compareNames(t.getFullNameUTF8(), i.getNameUTF8(), TreeEntry.lastChar(t), TreeEntry.lastChar(i));
  198. }
  199. static int compare(TreeEntry t1, TreeEntry t2) {
  200. if (t1 != null && t1.getParent() == null && t2 != null && t2.getParent() == null)
  201. return 0;
  202. if (t1 != null && t1.getParent() == null)
  203. return -1;
  204. if (t2 != null && t2.getParent() == null)
  205. return 1;
  206. if (t1 == null && t2 == null)
  207. return 0;
  208. if (t1 == null)
  209. return 1;
  210. if (t2 == null)
  211. return -1;
  212. return Tree.compareNames(t1.getFullNameUTF8(), t2.getFullNameUTF8(), TreeEntry.lastChar(t1), TreeEntry.lastChar(t2));
  213. }
  214. }