Support committing submodule updates

Use the submodule object id provided by the working
tree iterator

Change-Id: Ibf82f56c04cb9c91b2b309cf0cfa3f638539e23c
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
index 37fbc67..b9f5882 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
@@ -44,15 +44,25 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.util.List;
 
+import org.eclipse.jgit.diff.DiffEntry;
 import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.submodule.SubmoduleWalk;
 import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
 import org.eclipse.jgit.util.FS;
 import org.junit.Test;
 
@@ -152,4 +162,100 @@ public boolean canExecute(File f) {
 		assertNotNull(walk);
 		assertEquals(FileMode.EXECUTABLE_FILE, walk.getFileMode(0));
 	}
+
+	@Test
+	public void commitNewSubmodule() throws Exception {
+		Git git = new Git(db);
+		writeTrashFile("file.txt", "content");
+		git.add().addFilepattern("file.txt").call();
+		RevCommit commit = git.commit().setMessage("create file").call();
+
+		SubmoduleAddCommand command = new SubmoduleAddCommand(db);
+		String path = "sub";
+		command.setPath(path);
+		String uri = db.getDirectory().toURI().toString();
+		command.setURI(uri);
+		Repository repo = command.call();
+		assertNotNull(repo);
+
+		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
+		assertTrue(generator.next());
+		assertEquals(path, generator.getPath());
+		assertEquals(commit, generator.getObjectId());
+		assertEquals(uri, generator.getModulesUrl());
+		assertEquals(path, generator.getModulesPath());
+		assertEquals(uri, generator.getConfigUrl());
+		assertNotNull(generator.getRepository());
+		assertEquals(commit, repo.resolve(Constants.HEAD));
+
+		RevCommit submoduleCommit = git.commit().setMessage("submodule add")
+				.setOnly(path).call();
+		assertNotNull(submoduleCommit);
+		TreeWalk walk = new TreeWalk(db);
+		walk.addTree(commit.getTree());
+		walk.addTree(submoduleCommit.getTree());
+		walk.setFilter(TreeFilter.ANY_DIFF);
+		List<DiffEntry> diffs = DiffEntry.scan(walk);
+		assertEquals(1, diffs.size());
+		DiffEntry subDiff = diffs.get(0);
+		assertEquals(FileMode.MISSING, subDiff.getOldMode());
+		assertEquals(FileMode.GITLINK, subDiff.getNewMode());
+		assertEquals(ObjectId.zeroId(), subDiff.getOldId().toObjectId());
+		assertEquals(commit, subDiff.getNewId().toObjectId());
+		assertEquals(path, subDiff.getNewPath());
+	}
+
+	@Test
+	public void commitSubmoduleUpdate() throws Exception {
+		Git git = new Git(db);
+		writeTrashFile("file.txt", "content");
+		git.add().addFilepattern("file.txt").call();
+		RevCommit commit = git.commit().setMessage("create file").call();
+		writeTrashFile("file.txt", "content2");
+		git.add().addFilepattern("file.txt").call();
+		RevCommit commit2 = git.commit().setMessage("edit file").call();
+
+		SubmoduleAddCommand command = new SubmoduleAddCommand(db);
+		String path = "sub";
+		command.setPath(path);
+		String uri = db.getDirectory().toURI().toString();
+		command.setURI(uri);
+		Repository repo = command.call();
+		assertNotNull(repo);
+
+		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
+		assertTrue(generator.next());
+		assertEquals(path, generator.getPath());
+		assertEquals(commit2, generator.getObjectId());
+		assertEquals(uri, generator.getModulesUrl());
+		assertEquals(path, generator.getModulesPath());
+		assertEquals(uri, generator.getConfigUrl());
+		assertNotNull(generator.getRepository());
+		assertEquals(commit2, repo.resolve(Constants.HEAD));
+
+		RevCommit submoduleAddCommit = git.commit().setMessage("submodule add")
+				.setOnly(path).call();
+		assertNotNull(submoduleAddCommit);
+
+		RefUpdate update = repo.updateRef(Constants.HEAD);
+		update.setNewObjectId(commit);
+		assertEquals(Result.FORCED, update.forceUpdate());
+
+		RevCommit submoduleEditCommit = git.commit()
+				.setMessage("submodule add").setOnly(path).call();
+		assertNotNull(submoduleEditCommit);
+		TreeWalk walk = new TreeWalk(db);
+		walk.addTree(submoduleAddCommit.getTree());
+		walk.addTree(submoduleEditCommit.getTree());
+		walk.setFilter(TreeFilter.ANY_DIFF);
+		List<DiffEntry> diffs = DiffEntry.scan(walk);
+		assertEquals(1, diffs.size());
+		DiffEntry subDiff = diffs.get(0);
+		assertEquals(FileMode.GITLINK, subDiff.getOldMode());
+		assertEquals(FileMode.GITLINK, subDiff.getNewMode());
+		assertEquals(commit2, subDiff.getOldId().toObjectId());
+		assertEquals(commit, subDiff.getNewId().toObjectId());
+		assertEquals(path, subDiff.getNewPath());
+		assertEquals(path, subDiff.getOldPath());
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index d2386f1..882ce21 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -351,12 +351,9 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index)
 					if (objectExists) {
 						dcEntry.setObjectId(fTree.getEntryObjectId());
 					} else {
-						if (FileMode.GITLINK.equals(dcEntry.getFileMode())) {
-							// Do not check the content of submodule entries
-							// Use the old entry information instead.
-							dcEntry.copyMetaData(index.getEntry(dcEntry
-									.getPathString()));
-						} else {
+						if (FileMode.GITLINK.equals(dcEntry.getFileMode()))
+							dcEntry.setObjectId(fTree.getEntryObjectId());
+						else {
 							// insert object
 							if (inserter == null)
 								inserter = repo.newObjectInserter();