Add better documentation to DirCacheCheckout

Change-Id: I282b702d9e4cb19063d8e9503604538f80e955b7
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 7629de6..292206e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -683,6 +683,8 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
 		}
 
 		if (i == null) {
+			// Nothing in Index
+			// At least one of Head, Index, Merge is not empty
 			// make sure not to overwrite untracked files
 			if (f != null) {
 				// A submodule is not a file. We should ignore it
@@ -711,17 +713,37 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
 			 */
 
 			if (h == null)
+				// Nothing in Head
+				// Nothing in Index
+				// At least one of Head, Index, Merge is not empty
+				// -> only Merge contains something for this path. Use it!
+				// Potentially update the file
 				update(name, mId, mMode); // 1
 			else if (m == null)
+				// Nothing in Merge
+				// Something in Head
+				// Nothing in Index
+				// -> only Head contains something for this path and it should
+				// be deleted. Potentially removes the file!
 				remove(name); // 2
 			else { // 3
+				// Something in Merge
+				// Something in Head
+				// Nothing in Index
+				// -> Head and Merge contain something (maybe not the same) and
+				// in the index there is nothing (e.g. 'git rm ...' was
+				// called before). Ignore the cached deletion and use what we
+				// find in Merge. Potentially updates the file.
 				if (equalIdAndMode(hId, hMode, mId, mMode))
 					keep(dce);
 				else
 					conflict(name, dce, h, m);
 			}
 		} else {
+			// Something in Index
 			if (h == null) {
+				// Nothing in Head
+				// Something in Index
 				/**
 				 * <pre>
 				 * 	          clean I==H  I==M       H        M        Result
@@ -737,17 +759,54 @@ else if (m == null)
 				 */
 
 				if (m == null || equalIdAndMode(mId, mMode, iId, iMode)) {
+					// Merge contains nothing or the same as Index
+					// Nothing in Head
+					// Something in Index
 					if (m==null && walk.isDirectoryFileConflict()) {
+						// Nothing in Merge and current path is part of
+						// File/Folder conflict
+						// Nothing in Head
+						// Something in Index
 						if (dce != null
 								&& (f == null || f.isModified(dce, true)))
+							// No file or file is dirty
+							// Nothing in Merge and current path is part of
+							// File/Folder conflict
+							// Nothing in Head
+							// Something in Index
+							// -> File folder conflict and Merge wants this
+							// path to be removed. Since the file is dirty
+							// report a conflict
 							conflict(name, dce, h, m);
 						else
+							// A file is present and file is not dirty
+							// Nothing in Merge and current path is part of
+							// File/Folder conflict
+							// Nothing in Head
+							// Something in Index
+							// -> File folder conflict and Merge wants this path
+							// to be removed. Since the file is not dirty remove
+							// file and index entry
 							remove(name);
 					} else
+						// Something in Merge or current path is not part of
+						// File/Folder conflict
+						// Merge contains nothing or the same as Index
+						// Nothing in Head
+						// Something in Index
+						// -> Merge contains nothing new. Keep the index.
 						keep(dce);
 				} else
+					// Merge contains something and it is not the same as Index
+					// Nothing in Head
+					// Something in Index
+					// -> Index contains something new (different from Head)
+					// and Merge is different from Index. Report a conflict
 					conflict(name, dce, h, m);
 			} else if (m == null) {
+				// Nothing in Merge
+				// Something in Head
+				// Something in Index
 
 				/**
 				 * <pre>
@@ -761,36 +820,115 @@ else if (m == null)
 				 */
 
 				if (iMode == FileMode.GITLINK) {
+					// A submodule in Index
+					// Nothing in Merge
+					// Something in Head
 					// Submodules that disappear from the checkout must
 					// be removed from the index, but not deleted from disk.
 					remove(name);
 				} else {
+					// Something different from a submodule in Index
+					// Nothing in Merge
+					// Something in Head
 					if (equalIdAndMode(hId, hMode, iId, iMode)) {
+						// Index contains the same as Head
+						// Something different from a submodule in Index
+						// Nothing in Merge
+						// Something in Head
 						if (f == null || f.isModified(dce, true))
+							// file is dirty
+							// Index contains the same as Head
+							// Something different from a submodule in Index
+							// Nothing in Merge
+							// Something in Head
+							// -> file is dirty but is should be removed. That's
+							// a conflict
 							conflict(name, dce, h, m);
 						else
+							// file doesn't exist or is clean
+							// Index contains the same as Head
+							// Something different from a submodule in Index
+							// Nothing in Merge
+							// Something in Head
+							// -> Remove from index and delete the file
 							remove(name);
 					} else
+						// Index contains something different from Head
+						// Something different from a submodule in Index
+						// Nothing in Merge
+						// Something in Head
+						// -> Something new is in index (and maybe even on the
+						// filesystem). But Merge wants the path to be removed.
+						// Report a conflict
 						conflict(name, dce, h, m);
 				}
 			} else {
+				// Something in Merge
+				// Something in Head
+				// Something in Index
 				if (!equalIdAndMode(hId, hMode, mId, mMode)
 						&& !equalIdAndMode(hId, hMode, iId, iMode)
 						&& !equalIdAndMode(mId, mMode, iId, iMode))
+					// All three contents in Head, Merge, Index differ from each
+					// other
+					// -> All contents differ. Report a conflict.
 					conflict(name, dce, h, m);
-				else if (equalIdAndMode(hId, hMode, iId, iMode)
+				else
+					// At least two of the contents of Head, Index, Merge
+					// are the same
+					// Something in Merge
+					// Something in Head
+					// Something in Index
+
+					if (equalIdAndMode(hId, hMode, iId, iMode)
 						&& !equalIdAndMode(mId, mMode, iId, iMode)) {
+						// Head contains the same as Index. Merge differs
+						// Something in Merge
+
 					// For submodules just update the index with the new SHA-1
 					if (dce != null
 							&& FileMode.GITLINK.equals(dce.getFileMode())) {
+						// Index and Head contain the same submodule. Merge
+						// differs
+						// Something in Merge
+						// -> Nothing new in index. Move to merge.
+						// Potentially updates the file
+
+						// TODO check that we don't overwrite some unsaved
+						// file content
 						update(name, mId, mMode);
 					} else if (dce != null
 							&& (f == null || f.isModified(dce, true))) {
+						// File doesn't exist or is dirty
+						// Head and Index don't contain a submodule
+						// Head contains the same as Index. Merge differs
+						// Something in Merge
+						// -> Merge wants the index and file to be updated
+						// but the file is dirty. Report a conflict
 						conflict(name, dce, h, m);
 					} else {
+						// File exists and is clean
+						// Head and Index don't contain a submodule
+						// Head contains the same as Index. Merge differs
+						// Something in Merge
+						// -> Standard case when switching between branches:
+						// Nothing new in index but something different in
+						// Merge. Update index and file
 						update(name, mId, mMode);
 					}
 				} else {
+					// Head differs from index or merge is same as index
+					// At least two of the contents of Head, Index, Merge
+					// are the same
+					// Something in Merge
+					// Something in Head
+					// Something in Index
+
+					// Can be formulated as: Either all three states are
+					// equal or Merge is equal to Head or Index and differs
+					// to the other one.
+					// -> In all three cases we don't touch index and file.
+
 					keep(dce);
 				}
 			}