TestRepository: Add methods to amend commits or refs
Change-Id: I47082416f6e281262b160ba15272258f9109abd1
This commit is contained in:
parent
d79cadb3cf
commit
da85ca73ff
|
@ -435,6 +435,72 @@ public RevCommit update(String ref, CommitBuilder to) throws Exception {
|
||||||
return update(ref, to.create());
|
return update(ref, to.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amend an existing ref.
|
||||||
|
*
|
||||||
|
* @param ref
|
||||||
|
* the name of the reference to amend, which must already exist.
|
||||||
|
* If {@code ref} does not start with {@code refs/} and is not the
|
||||||
|
* magic names {@code HEAD} {@code FETCH_HEAD} or {@code
|
||||||
|
* MERGE_HEAD}, then {@code refs/heads/} will be prefixed in front
|
||||||
|
* of the given name, thereby assuming it is a branch.
|
||||||
|
* @return commit builder that amends the branch on commit.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public CommitBuilder amendRef(String ref) throws Exception {
|
||||||
|
String name = normalizeRef(ref);
|
||||||
|
Ref r = db.getRef(name);
|
||||||
|
if (r == null)
|
||||||
|
throw new IOException("Not a ref: " + ref);
|
||||||
|
return amend(pool.parseCommit(r.getObjectId()), branch(name).commit());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amend an existing commit.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the id of the commit to amend.
|
||||||
|
* @return commit builder.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public CommitBuilder amend(AnyObjectId id) throws Exception {
|
||||||
|
return amend(pool.parseCommit(id), commit());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommitBuilder amend(RevCommit old, CommitBuilder b) throws Exception {
|
||||||
|
pool.parseBody(old);
|
||||||
|
b.author(old.getAuthorIdent());
|
||||||
|
b.committer(old.getCommitterIdent());
|
||||||
|
b.message(old.getFullMessage());
|
||||||
|
// Use the committer name from the old commit, but update it after ticking
|
||||||
|
// the clock in CommitBuilder#create().
|
||||||
|
b.updateCommitterTime = true;
|
||||||
|
|
||||||
|
// Reset parents to original parents.
|
||||||
|
b.noParents();
|
||||||
|
for (int i = 0; i < old.getParentCount(); i++)
|
||||||
|
b.parent(old.getParent(i));
|
||||||
|
|
||||||
|
// Reset tree to original tree; resetting parents reset tree contents to the
|
||||||
|
// first parent.
|
||||||
|
b.tree.clear();
|
||||||
|
try (TreeWalk tw = new TreeWalk(db)) {
|
||||||
|
tw.reset(old.getTree());
|
||||||
|
tw.setRecursive(true);
|
||||||
|
while (tw.next()) {
|
||||||
|
b.edit(new PathEdit(tw.getPathString()) {
|
||||||
|
@Override
|
||||||
|
public void apply(DirCacheEntry ent) {
|
||||||
|
ent.setFileMode(tw.getFileMode(0));
|
||||||
|
ent.setObjectId(tw.getObjectId(0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a reference to point to an object.
|
* Update a reference to point to an object.
|
||||||
*
|
*
|
||||||
|
@ -452,17 +518,7 @@ public RevCommit update(String ref, CommitBuilder to) throws Exception {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
|
public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
|
||||||
if (Constants.HEAD.equals(ref)) {
|
ref = normalizeRef(ref);
|
||||||
// nothing
|
|
||||||
} else if ("FETCH_HEAD".equals(ref)) {
|
|
||||||
// nothing
|
|
||||||
} else if ("MERGE_HEAD".equals(ref)) {
|
|
||||||
// nothing
|
|
||||||
} else if (ref.startsWith(Constants.R_REFS)) {
|
|
||||||
// nothing
|
|
||||||
} else
|
|
||||||
ref = Constants.R_HEADS + ref;
|
|
||||||
|
|
||||||
RefUpdate u = db.updateRef(ref);
|
RefUpdate u = db.updateRef(ref);
|
||||||
u.setNewObjectId(obj);
|
u.setNewObjectId(obj);
|
||||||
switch (u.forceUpdate()) {
|
switch (u.forceUpdate()) {
|
||||||
|
@ -478,6 +534,20 @@ public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String normalizeRef(String ref) {
|
||||||
|
if (Constants.HEAD.equals(ref)) {
|
||||||
|
// nothing
|
||||||
|
} else if ("FETCH_HEAD".equals(ref)) {
|
||||||
|
// nothing
|
||||||
|
} else if ("MERGE_HEAD".equals(ref)) {
|
||||||
|
// nothing
|
||||||
|
} else if (ref.startsWith(Constants.R_REFS)) {
|
||||||
|
// nothing
|
||||||
|
} else
|
||||||
|
ref = Constants.R_HEADS + ref;
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Soft-reset HEAD to a detached state.
|
* Soft-reset HEAD to a detached state.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -807,6 +877,8 @@ public class CommitBuilder {
|
||||||
|
|
||||||
private boolean insertChangeId;
|
private boolean insertChangeId;
|
||||||
|
|
||||||
|
private boolean updateCommitterTime;
|
||||||
|
|
||||||
CommitBuilder() {
|
CommitBuilder() {
|
||||||
branch = null;
|
branch = null;
|
||||||
}
|
}
|
||||||
|
@ -930,8 +1002,11 @@ public RevCommit create() throws Exception {
|
||||||
setAuthorAndCommitter(c);
|
setAuthorAndCommitter(c);
|
||||||
if (author != null)
|
if (author != null)
|
||||||
c.setAuthor(author);
|
c.setAuthor(author);
|
||||||
if (committer != null)
|
if (committer != null) {
|
||||||
|
if (updateCommitterTime)
|
||||||
|
committer = new PersonIdent(committer, new Date(now));
|
||||||
c.setCommitter(committer);
|
c.setCommitter(committer);
|
||||||
|
}
|
||||||
|
|
||||||
ObjectId commitId;
|
ObjectId commitId;
|
||||||
try (ObjectInserter ins = inserter) {
|
try (ObjectInserter ins = inserter) {
|
||||||
|
|
|
@ -43,19 +43,29 @@
|
||||||
|
|
||||||
package org.eclipse.jgit.junit;
|
package org.eclipse.jgit.junit;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
|
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
|
||||||
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
|
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.ObjectLoader;
|
||||||
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.revwalk.RevObject;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -76,7 +86,7 @@ public void setUp() throws Exception {
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
rw.close();
|
rw.close();
|
||||||
tr.getRepository().close();
|
repo.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -168,4 +178,98 @@ public void resetFromDetachedHead() throws Exception {
|
||||||
assertEquals(detached, head.getObjectId());
|
assertEquals(detached, head.getObjectId());
|
||||||
assertFalse(head.isSymbolic());
|
assertFalse(head.isSymbolic());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void amendRef() throws Exception {
|
||||||
|
RevCommit root = tr.commit()
|
||||||
|
.add("todelete", "to be deleted")
|
||||||
|
.create();
|
||||||
|
RevCommit orig = tr.commit().parent(root)
|
||||||
|
.rm("todelete")
|
||||||
|
.add("foo", "foo contents")
|
||||||
|
.add("bar", "bar contents")
|
||||||
|
.add("dir/baz", "baz contents")
|
||||||
|
.create();
|
||||||
|
rw.parseBody(orig);
|
||||||
|
tr.branch("master").update(orig);
|
||||||
|
assertEquals("foo contents", blobAsString(orig, "foo"));
|
||||||
|
assertEquals("bar contents", blobAsString(orig, "bar"));
|
||||||
|
assertEquals("baz contents", blobAsString(orig, "dir/baz"));
|
||||||
|
|
||||||
|
RevCommit amended = tr.amendRef("master")
|
||||||
|
.tick(3)
|
||||||
|
.add("bar", "fixed bar contents")
|
||||||
|
.create();
|
||||||
|
assertEquals(amended, repo.getRef("refs/heads/master").getObjectId());
|
||||||
|
rw.parseBody(amended);
|
||||||
|
|
||||||
|
assertEquals(1, amended.getParentCount());
|
||||||
|
assertEquals(root, amended.getParent(0));
|
||||||
|
assertEquals(orig.getFullMessage(), amended.getFullMessage());
|
||||||
|
assertEquals(orig.getAuthorIdent(), amended.getAuthorIdent());
|
||||||
|
|
||||||
|
// Committer name/email is the same, but time was incremented.
|
||||||
|
assertEquals(new PersonIdent(orig.getCommitterIdent(), new Date(0)),
|
||||||
|
new PersonIdent(amended.getCommitterIdent(), new Date(0)));
|
||||||
|
assertTrue(orig.getCommitTime() < amended.getCommitTime());
|
||||||
|
|
||||||
|
assertEquals("foo contents", blobAsString(amended, "foo"));
|
||||||
|
assertEquals("fixed bar contents", blobAsString(amended, "bar"));
|
||||||
|
assertEquals("baz contents", blobAsString(amended, "dir/baz"));
|
||||||
|
assertNull(TreeWalk.forPath(repo, "todelete", amended.getTree()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void amendHead() throws Exception {
|
||||||
|
repo.updateRef("HEAD").link("refs/heads/master");
|
||||||
|
RevCommit root = tr.commit()
|
||||||
|
.add("foo", "foo contents")
|
||||||
|
.create();
|
||||||
|
RevCommit orig = tr.commit().parent(root)
|
||||||
|
.message("original message")
|
||||||
|
.add("bar", "bar contents")
|
||||||
|
.create();
|
||||||
|
tr.branch("master").update(orig);
|
||||||
|
|
||||||
|
RevCommit amended = tr.amendRef("HEAD")
|
||||||
|
.add("foo", "fixed foo contents")
|
||||||
|
.create();
|
||||||
|
|
||||||
|
Ref head = repo.getRef(Constants.HEAD);
|
||||||
|
assertEquals(amended, head.getObjectId());
|
||||||
|
assertTrue(head.isSymbolic());
|
||||||
|
assertEquals("refs/heads/master", head.getTarget().getName());
|
||||||
|
|
||||||
|
rw.parseBody(amended);
|
||||||
|
assertEquals("original message", amended.getFullMessage());
|
||||||
|
assertEquals("fixed foo contents", blobAsString(amended, "foo"));
|
||||||
|
assertEquals("bar contents", blobAsString(amended, "bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void amendCommit() throws Exception {
|
||||||
|
RevCommit root = tr.commit()
|
||||||
|
.add("foo", "foo contents")
|
||||||
|
.create();
|
||||||
|
RevCommit orig = tr.commit().parent(root)
|
||||||
|
.message("original message")
|
||||||
|
.add("bar", "bar contents")
|
||||||
|
.create();
|
||||||
|
RevCommit amended = tr.amend(orig.copy())
|
||||||
|
.add("foo", "fixed foo contents")
|
||||||
|
.create();
|
||||||
|
|
||||||
|
rw.parseBody(amended);
|
||||||
|
assertEquals("original message", amended.getFullMessage());
|
||||||
|
assertEquals("fixed foo contents", blobAsString(amended, "foo"));
|
||||||
|
assertEquals("bar contents", blobAsString(amended, "bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String blobAsString(AnyObjectId treeish, String path)
|
||||||
|
throws Exception {
|
||||||
|
RevObject obj = tr.get(rw.parseTree(treeish), path);
|
||||||
|
assertSame(RevBlob.class, obj.getClass());
|
||||||
|
ObjectLoader loader = rw.getObjectReader().open(obj);
|
||||||
|
return new String(loader.getCachedBytes(), UTF_8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue