InlineEdit: Add method to rebase change edit

Change-Id: I09bbf692bc7812df5f608fc87455aa673b9f0cf9
This commit is contained in:
David Ostrovsky
2014-08-10 23:55:19 +02:00
parent 0816c75e1c
commit 14fcdd7458
3 changed files with 121 additions and 7 deletions

View File

@@ -3,4 +3,5 @@ include_defs('//gerrit-acceptance-tests/tests.defs')
acceptance_tests(
srcs = ['ChangeEditIT.java'],
labels = ['edit'],
deps = ['//lib/joda:joda-time'],
)

View File

@@ -15,6 +15,8 @@
package com.google.gerrit.acceptance.edit;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -46,11 +48,16 @@ import com.google.inject.util.Providers;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.DateTimeUtils.MillisProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
@NoHttpd
public class ChangeEditIT extends AbstractDaemonTest {
@@ -84,6 +91,7 @@ public class ChangeEditIT extends AbstractDaemonTest {
private ReviewDb db;
private Change change;
private String changeId;
private Change change2;
private PatchSet ps;
private PatchSet ps2;
@@ -92,22 +100,33 @@ public class ChangeEditIT extends AbstractDaemonTest {
@Before
public void setUp() throws Exception {
db = reviewDbProvider.open();
String changeId = newChange(git, admin.getIdent());
change = getChange(changeId);
changeId = newChange(git, admin.getIdent());
ps = getCurrentPatchSet(changeId);
amendChange(git, admin.getIdent(), changeId);
change = getChange(changeId);
assertNotNull(ps);
changeId = newChange2(git, admin.getIdent());
change2 = getChange(changeId);
String changeId2 = newChange2(git, admin.getIdent());
change2 = getChange(changeId2);
assertNotNull(change2);
ps2 = getCurrentPatchSet(changeId);
ps2 = getCurrentPatchSet(changeId2);
assertNotNull(ps2);
session = new RestSession(server, admin);
atrScope.set(atrScope.newContext(reviewDbProvider, sshSession,
identifiedUserFactory.create(Providers.of(db), admin.getId())));
final long clockStepMs = MILLISECONDS.convert(1, SECONDS);
final AtomicLong clockMs = new AtomicLong(
new DateTime(2009, 9, 30, 17, 0, 0).getMillis());
DateTimeUtils.setCurrentMillisProvider(new MillisProvider() {
@Override
public long getMillis() {
return clockMs.getAndAdd(clockStepMs);
}
});
}
@After
public void cleanup() {
DateTimeUtils.setCurrentMillisSystem();
db.close();
}
@@ -128,6 +147,21 @@ public class ChangeEditIT extends AbstractDaemonTest {
@Test
public void publishEdit() throws Exception {
assertEquals(RefUpdate.Result.NEW,
modifier.createEdit(
change,
getCurrentPatchSet(changeId)));
assertEquals(RefUpdate.Result.FORCED,
modifier.modifyFile(
editUtil.byChange(change).get(),
FILE_NAME,
CONTENT_NEW2));
editUtil.publish(editUtil.byChange(change).get());
assertFalse(editUtil.byChange(change).isPresent());
}
@Test
public void rebaseEdit() throws Exception {
assertEquals(RefUpdate.Result.NEW,
modifier.createEdit(
change,
@@ -137,8 +171,23 @@ public class ChangeEditIT extends AbstractDaemonTest {
editUtil.byChange(change).get(),
FILE_NAME,
CONTENT_NEW));
editUtil.publish(editUtil.byChange(change).get());
assertFalse(editUtil.byChange(change).isPresent());
ChangeEdit edit = editUtil.byChange(change).get();
PatchSet current = getCurrentPatchSet(changeId);
assertEquals(current.getPatchSetId() - 1,
edit.getBasePatchSet().getPatchSetId());
Date beforeRebase = edit.getEditCommit().getCommitterIdent().getWhen();
modifier.rebaseEdit(edit, current);
edit = editUtil.byChange(change).get();
assertArrayEquals(CONTENT_NEW,
toBytes(fileUtil.getContent(edit.getChange().getProject(),
edit.getRevision().get(), FILE_NAME)));
assertArrayEquals(CONTENT_NEW2,
toBytes(fileUtil.getContent(edit.getChange().getProject(),
edit.getRevision().get(), FILE_NAME2)));
assertEquals(current.getPatchSetId(),
edit.getBasePatchSet().getPatchSetId());
Date afterRebase = edit.getEditCommit().getCommitterIdent().getWhen();
assertFalse(beforeRebase.equals(afterRebase));
}
@Test
@@ -332,6 +381,13 @@ public class ChangeEditIT extends AbstractDaemonTest {
return push.to(git, "refs/for/master").getChangeId();
}
private String amendChange(Git git, PersonIdent ident, String changeId) throws Exception {
PushOneCommit push =
pushFactory.create(db, ident, PushOneCommit.SUBJECT, FILE_NAME2,
new String(CONTENT_NEW2), changeId);
return push.to(git, "refs/for/master").getChangeId();
}
private String newChange2(Git git, PersonIdent ident) throws Exception {
PushOneCommit push =
pushFactory.create(db, ident, PushOneCommit.SUBJECT, FILE_NAME,

View File

@@ -46,6 +46,8 @@ import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -126,6 +128,61 @@ public class ChangeEditModifier {
}
}
/**
* Rebase change edit on latest patch set
*
* @param edit change edit that contains edit to rebase
* @param current patch set to rebase the edit on
* @throws AuthException
* @throws InvalidChangeOperationException
* @throws IOException
*/
public RefUpdate.Result rebaseEdit(ChangeEdit edit, PatchSet current)
throws AuthException, InvalidChangeOperationException, IOException {
if (!currentUser.get().isIdentifiedUser()) {
throw new AuthException("Authentication required");
}
Change change = edit.getChange();
IdentifiedUser me = (IdentifiedUser) currentUser.get();
String refName = editRefName(me.getAccountId(), change.getId());
Repository repo = gitManager.openRepository(change.getProject());
try {
RevWalk rw = new RevWalk(repo);
ObjectInserter inserter = repo.newObjectInserter();
try {
RevCommit editCommit = edit.getEditCommit();
RevCommit mergeTip = rw.parseCommit(ObjectId.fromString(
current.getRevision().get()));
ThreeWayMerger m = MergeStrategy.RESOLVE.newMerger(repo, true);
m.setObjectInserter(inserter);
m.setBase(editCommit.getParent(0));
if (m.merge(mergeTip, editCommit)) {
ObjectId tree = m.getResultTreeId();
CommitBuilder mergeCommit = new CommitBuilder();
mergeCommit.setTreeId(tree);
mergeCommit.setParentId(mergeTip);
mergeCommit.setAuthor(editCommit.getAuthorIdent());
mergeCommit.setCommitter(new PersonIdent(
editCommit.getCommitterIdent(), TimeUtil.nowTs()));
mergeCommit.setMessage(editCommit.getFullMessage());
ObjectId newEdit = inserter.insert(mergeCommit);
inserter.flush();
return update(repo, me, refName, rw, editCommit, newEdit);
} else {
// TODO(davido): Allow to resolve conflicts inline
throw new InvalidChangeOperationException("merge conflict");
}
} finally {
rw.release();
inserter.release();
}
} finally {
repo.close();
}
}
/**
* Modify file in existing change edit from its base commit.
*