Drop some unused code in jgit
[egit.git] / org.spearce.jgit / src / org / spearce / jgit / lib / WorkDirCheckout.java
blob6ab7cbadf17fa76a21f92c3445fa7f1fba05bf0b
1 /*
2 * Copyright (C) 2007 Dave Watson <dwatson@mimvista.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.jgit.lib;
19 import java.io.File;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashMap;
25 import org.spearce.jgit.errors.CheckoutConflictException;
26 import org.spearce.jgit.lib.GitIndex.Entry;
28 public class WorkDirCheckout {
29 protected Repository repo;
31 protected File root;
33 protected GitIndex index;
35 private boolean failOnConflict = true;
37 protected Tree merge;
40 /**
41 * If <code>true</code>, will scan first to see if it's possible to check out,
42 * otherwise throw {@link CheckoutConflictException}. If <code>false</code>,
43 * it will silently deal with the problem.
44 * @param failOnConflict
46 public void setFailOnConflict(boolean failOnConflict) {
47 this.failOnConflict = failOnConflict;
50 WorkDirCheckout(Repository repo, File workDir,
51 GitIndex oldIndex, GitIndex newIndex) throws IOException {
52 this.repo = repo;
53 this.root = workDir;
54 this.index = oldIndex;
55 this.merge = repo.mapTree(newIndex.writeTree());
58 public WorkDirCheckout(Repository repo, File root,
59 GitIndex index, Tree merge) {
60 this.repo = repo;
61 this.root = root;
62 this.index = index;
63 this.merge = merge;
66 public WorkDirCheckout(Repository repo, File root, Tree head, GitIndex index, Tree merge) {
67 this(repo, root, index, merge);
68 this.head = head;
71 public void checkout() throws IOException {
72 if (head == null)
73 prescanOneTree();
74 else prescanTwoTrees();
75 if (!conflicts.isEmpty()) {
76 if (failOnConflict) {
77 String[] entries = conflicts.toArray(new String[0]);
78 throw new CheckoutConflictException(entries);
82 cleanUpConflicts();
83 if (head == null)
84 checkoutOutIndexNoHead();
85 else checkoutTwoTrees();
88 private void checkoutTwoTrees() throws FileNotFoundException, IOException {
89 for (String path : removed) {
90 index.remove(root, new File(root, path));
93 for (java.util.Map.Entry<String, ObjectId> entry : updated.entrySet()) {
94 Entry newEntry = index.addEntry(merge.findBlobMember(entry.getKey()));
95 index.checkoutEntry(root, newEntry);
99 ArrayList<String> conflicts = new ArrayList<String>();;
100 ArrayList<String> removed = new ArrayList<String>();
102 protected Tree head = null;
104 protected HashMap<String, ObjectId> updated = new HashMap<String, ObjectId>();
106 private void checkoutOutIndexNoHead() throws IOException {
107 new IndexTreeWalker(index, merge, root, new AbstractIndexTreeVisitor() {
108 public void visitEntry(TreeEntry m, Entry i, File f) throws IOException {
109 if (m == null) {
110 index.remove(root, f);
111 return;
114 boolean needsCheckout = false;
115 if (i == null)
116 needsCheckout = true;
117 else if (i.getObjectId().equals(m.getId())) {
118 if (i.isModified(root, true))
119 needsCheckout = true;
120 } else needsCheckout = true;
122 if (needsCheckout) {
123 Entry newEntry = index.addEntry(m);
124 index.checkoutEntry(root, newEntry);
127 }).walk();
130 private void cleanUpConflicts() throws CheckoutConflictException {
131 for (String c : conflicts) {
132 File conflict = new File(root, c);
133 if (!conflict.delete())
134 throw new CheckoutConflictException("Cannot delete file: " + c);
135 removeEmptyParents(conflict);
137 for (String r : removed) {
138 File file = new File(root, r);
139 file.delete();
140 removeEmptyParents(file);
144 private void removeEmptyParents(File f) {
145 File parentFile = f.getParentFile();
146 while (!parentFile.equals(root)) {
147 if (parentFile.list().length == 0)
148 parentFile.delete();
149 else break;
151 parentFile = parentFile.getParentFile();
155 void prescanOneTree() throws IOException {
156 new IndexTreeWalker(index, merge, root, new AbstractIndexTreeVisitor() {
157 public void visitEntry(TreeEntry m, Entry i, File file) throws IOException {
158 if (m != null) {
159 if (!file.isFile()) {
160 checkConflictsWithFile(file);
162 } else {
163 if (file.exists()) {
164 removed.add(i.getName());
165 conflicts.remove(i.getName());
169 }).walk();
170 conflicts.removeAll(removed);
173 private ArrayList<String> listFiles(File file) {
174 ArrayList<String> list = new ArrayList<String>();
175 listFiles(file, list);
176 return list;
179 private void listFiles(File dir, ArrayList<String> list) {
180 for (File f : dir.listFiles()) {
181 if (f.isDirectory())
182 listFiles(f, list);
183 else {
184 list.add(stripWorkdirFront(f));
189 private String stripWorkdirFront(File f) {
190 return f.getPath().substring(root.getPath().length() + 1);
193 public ArrayList<String> getConflicts() {
194 return conflicts;
197 public ArrayList<String> getRemoved() {
198 return removed;
201 void prescanTwoTrees() throws IOException {
202 new IndexTreeWalker(index, head, merge, root, new AbstractIndexTreeVisitor() {
203 public void visitEntry(TreeEntry treeEntry, TreeEntry auxEntry,
204 Entry indexEntry, File file) throws IOException {
205 if (treeEntry instanceof Tree || auxEntry instanceof Tree) {
206 throw new IllegalArgumentException("Can't pass me a tree!");
208 processEntry(treeEntry, auxEntry, indexEntry, file);
211 @Override
212 public void finishVisitTree(Tree tree, Tree auxTree, int i,
213 String curDir) throws IOException {
214 if (curDir.length() == 0) return;
216 if (auxTree != null && i == 0) {
217 if (index.getEntry(curDir) != null)
218 removed.add(curDir);
222 }).walk();
224 // if there's a conflict, don't list it under
225 // to-be-removed, since that messed up our next
226 // section
227 removed.removeAll(conflicts);
229 for (String path : updated.keySet()) {
230 if (index.getEntry(path) == null) {
231 File file = new File(root, path);
232 if (file.isFile())
233 conflicts.add(path);
234 else if (file.isDirectory()) {
235 checkConflictsWithFile(file);
241 conflicts.removeAll(removed);
244 protected void processEntry(TreeEntry h, TreeEntry m, Entry i,
245 File file) throws IOException {
246 ObjectId iId = (i == null ? null : i.getObjectId());
247 ObjectId mId = (m == null ? null : m.getId());
248 ObjectId hId = (h == null ? null : h.getId());
250 String name = (i != null ? i.getName() :
251 (h != null ? h.getFullName() :
252 m.getFullName()));
254 if (i == null) {
256 I (index) H M Result
257 -------------------------------------------------------
258 0 nothing nothing nothing (does not happen)
259 1 nothing nothing exists use M
260 2 nothing exists nothing remove path from index
261 3 nothing exists exists use M */
263 if (h == null) {
264 updated.put(name,mId);
265 } else if (m == null) {
266 removed.add(name);
267 } else {
268 updated.put(name, mId);
270 } else if (h == null) {
272 clean I==H I==M H M Result
273 -----------------------------------------------------
274 4 yes N/A N/A nothing nothing keep index
275 5 no N/A N/A nothing nothing keep index
277 6 yes N/A yes nothing exists keep index
278 7 no N/A yes nothing exists keep index
279 8 yes N/A no nothing exists fail
280 9 no N/A no nothing exists fail */
282 if (m == null || mId.equals(iId)) {
283 if (hasParentBlob(merge, name)) {
284 if (i.isModified(root, true)) {
285 conflicts.add(name);
286 } else {
287 removed.add(name);
290 } else {
291 conflicts.add(name);
293 } else if (m == null) {
295 10 yes yes N/A exists nothing remove path from index
296 11 no yes N/A exists nothing fail
297 12 yes no N/A exists nothing fail
298 13 no no N/A exists nothing fail
301 if (hId.equals(iId)) {
302 if (i.isModified(root, true)) {
303 conflicts.add(name);
304 } else {
305 removed.add(name);
307 } else {
308 conflicts.add(name);
310 } else {
311 if (!hId.equals(mId) && !hId.equals(iId)
312 && !mId.equals(iId)) {
313 conflicts.add(name);
314 } else if (hId.equals(iId) && !mId.equals(iId)) {
315 if (i.isModified(root, true))
316 conflicts.add(name);
317 else updated.put(name, mId);
322 private boolean hasParentBlob(Tree t, String name) throws IOException {
323 if (name.indexOf("/") == -1) return false;
325 String parent = name.substring(0, name.lastIndexOf("/"));
326 if (t.findBlobMember(parent) != null)
327 return true;
328 return hasParentBlob(t, parent);
331 private void checkConflictsWithFile(File file) {
332 if (file.isDirectory()) {
333 ArrayList<String> childFiles = listFiles(file);
334 conflicts.addAll(childFiles);
335 } else {
336 File parent = file.getParentFile();
337 while (!parent.equals(root)) {
338 if (parent.isDirectory())
339 break;
340 if (parent.isFile()) {
341 conflicts.add(stripWorkdirFront(parent));
342 break;
344 parent = parent.getParentFile();