Fix VersionedMetaData for multiple commits in one batch
I noticed that if you make a modification to the notes tree (i.e. insert comments) and then make a modification to the commit at the meta ref (i.e. insert approvals) within one BatchMetaDataUpdate, then the notes tree update will be squashed by the second update. I added tests to show this case and corrected this by using the tree from the parent commit unless there are new contents in the DirCache to be written. Change-Id: I83f09e08f472c21dc4bc06f00c3706a18d170f9c
This commit is contained in:
@@ -240,13 +240,23 @@ public abstract class VersionedMetaData {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectId res = newTree.writeTree(inserter);
|
// Reuse tree from parent commit unless there are contents in newTree or
|
||||||
|
// there is no tree for a parent commit.
|
||||||
|
ObjectId res = newTree.getEntryCount() != 0 || srcTree == null
|
||||||
|
? newTree.writeTree(inserter) : srcTree.copy();
|
||||||
if (res.equals(srcTree) && !update.allowEmpty()
|
if (res.equals(srcTree) && !update.allowEmpty()
|
||||||
&& (commit.getTreeId() == null)) {
|
&& (commit.getTreeId() == null)) {
|
||||||
// If there are no changes to the content, don't create the commit.
|
// If there are no changes to the content, don't create the commit.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If changes are made to the DirCache and those changes are written as
|
||||||
|
// a commit and then the tree ID is set for the CommitBuilder, then
|
||||||
|
// those previous DirCache changes will be ignored and the commit's
|
||||||
|
// tree will be replaced with the ID in the CommitBuilder. The same is
|
||||||
|
// true if you explicitly set tree ID in a commit and then make changes
|
||||||
|
// to the DirCache; that tree ID will be ignored and replaced by that of
|
||||||
|
// the tree for the updated DirCache.
|
||||||
if (commit.getTreeId() == null) {
|
if (commit.getTreeId() == null) {
|
||||||
commit.setTreeId(res);
|
commit.setTreeId(res);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ public class ChangeUpdate extends AbstractChangeUpdate {
|
|||||||
builder.setTreeId(treeId);
|
builder.setTreeId(treeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch.write(builder);
|
batch.write(this, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableListMultimap;
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
import com.google.common.collect.ImmutableSetMultimap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.LinkedListMultimap;
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
@@ -47,7 +48,9 @@ import org.eclipse.jgit.lib.BatchRefUpdate;
|
|||||||
import org.eclipse.jgit.lib.CommitBuilder;
|
import org.eclipse.jgit.lib.CommitBuilder;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.notes.Note;
|
import org.eclipse.jgit.notes.Note;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
import org.eclipse.jgit.transport.ReceiveCommand;
|
import org.eclipse.jgit.transport.ReceiveCommand;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -375,6 +378,62 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
|
|||||||
assertEquals((short) 2, psas.get(1).getValue());
|
assertEquals((short) 2, psas.get(1).getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleUpdatesIncludingComments() throws Exception {
|
||||||
|
Change c = newChange();
|
||||||
|
ChangeUpdate update1 = newUpdate(c, otherUser);
|
||||||
|
String uuid1 = "uuid1";
|
||||||
|
String message1 = "comment 1";
|
||||||
|
CommentRange range1 = new CommentRange(1, 1, 2, 1);
|
||||||
|
Timestamp time1 = TimeUtil.nowTs();
|
||||||
|
PatchSet.Id psId = c.currentPatchSetId();
|
||||||
|
BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
|
||||||
|
BatchMetaDataUpdate batch = update1.openUpdateInBatch(bru);
|
||||||
|
PatchLineComment comment1 = newPublishedPatchLineComment(psId, "file1",
|
||||||
|
uuid1, range1, range1.getEndLine(), otherUser, null, time1, message1,
|
||||||
|
(short) 0, "abcd1234abcd1234abcd1234abcd1234abcd1234");
|
||||||
|
update1.setPatchSetId(psId);
|
||||||
|
update1.upsertComment(comment1);
|
||||||
|
update1.writeCommit(batch);
|
||||||
|
ChangeUpdate update2 = newUpdate(c, otherUser);
|
||||||
|
update2.putApproval("Code-Review", (short) 2);
|
||||||
|
update2.writeCommit(batch);
|
||||||
|
|
||||||
|
RevWalk rw = new RevWalk(repo);
|
||||||
|
try {
|
||||||
|
batch.commit();
|
||||||
|
bru.execute(rw, NullProgressMonitor.INSTANCE);
|
||||||
|
|
||||||
|
ChangeNotes notes = newNotes(c);
|
||||||
|
ObjectId tip = notes.getRevision();
|
||||||
|
RevCommit commitWithApprovals = rw.parseCommit(tip);
|
||||||
|
assertNotNull(commitWithApprovals);
|
||||||
|
RevCommit commitWithComments = commitWithApprovals.getParent(0);
|
||||||
|
assertNotNull(commitWithComments);
|
||||||
|
|
||||||
|
ChangeNotesParser notesWithComments =
|
||||||
|
new ChangeNotesParser(c, commitWithComments.copy(), rw, repoManager);
|
||||||
|
notesWithComments.parseAll();
|
||||||
|
ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals1 =
|
||||||
|
notesWithComments.buildApprovals();
|
||||||
|
assertEquals(0, approvals1.size());
|
||||||
|
assertEquals(1, notesWithComments.commentsForBase.size());
|
||||||
|
notesWithComments.close();
|
||||||
|
|
||||||
|
ChangeNotesParser notesWithApprovals =
|
||||||
|
new ChangeNotesParser(c, commitWithApprovals.copy(), rw, repoManager);
|
||||||
|
notesWithApprovals.parseAll();
|
||||||
|
ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals2 =
|
||||||
|
notesWithApprovals.buildApprovals();
|
||||||
|
assertEquals(1, approvals2.size());
|
||||||
|
assertEquals(1, notesWithApprovals.commentsForBase.size());
|
||||||
|
notesWithApprovals.close();
|
||||||
|
} finally {
|
||||||
|
batch.close();
|
||||||
|
rw.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multipleUpdatesAcrossRefs() throws Exception {
|
public void multipleUpdatesAcrossRefs() throws Exception {
|
||||||
Change c1 = newChange();
|
Change c1 = newChange();
|
||||||
|
|||||||
Reference in New Issue
Block a user