]> source.dussan.org Git - jgit.git/commitdiff
TestRepository: Add methods to amend commits or refs 00/43700/8
authorDave Borowitz <dborowitz@google.com>
Wed, 11 Mar 2015 19:04:10 +0000 (12:04 -0700)
committerDave Borowitz <dborowitz@google.com>
Thu, 12 Mar 2015 19:46:24 +0000 (12:46 -0700)
Change-Id: I47082416f6e281262b160ba15272258f9109abd1

org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java

index 479ac7e5cf79a4a7a13a6d0c8e25464ed938fab2..6abd34d6f1cf4d02a5650b9956923fe441aa7ff5 100644 (file)
@@ -435,6 +435,72 @@ public class TestRepository<R extends Repository> {
                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.
         *
@@ -452,17 +518,7 @@ public class TestRepository<R extends Repository> {
         * @throws Exception
         */
        public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
-               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;
-
+               ref = normalizeRef(ref);
                RefUpdate u = db.updateRef(ref);
                u.setNewObjectId(obj);
                switch (u.forceUpdate()) {
@@ -478,6 +534,20 @@ public class TestRepository<R extends Repository> {
                }
        }
 
+       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.
         * <p>
@@ -807,6 +877,8 @@ public class TestRepository<R extends Repository> {
 
                private boolean insertChangeId;
 
+               private boolean updateCommitterTime;
+
                CommitBuilder() {
                        branch = null;
                }
@@ -930,8 +1002,11 @@ public class TestRepository<R extends Repository> {
                                setAuthorAndCommitter(c);
                                if (author != null)
                                        c.setAuthor(author);
-                               if (committer != null)
+                               if (committer != null) {
+                                       if (updateCommitterTime)
+                                               committer = new PersonIdent(committer, new Date(now));
                                        c.setCommitter(committer);
+                               }
 
                                ObjectId commitId;
                                try (ObjectInserter ins = inserter) {
index c14b32e6cc7f8ec2344a00a7fa5911287defcf06..cc8ed504d00312ff8d5531a9279881b1a9b81376 100644 (file)
 
 package org.eclipse.jgit.junit;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Date;
 import java.util.regex.Pattern;
 
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 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.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -76,7 +86,7 @@ public class TestRepositoryTest {
        @After
        public void tearDown() {
                rw.close();
-               tr.getRepository().close();
+               repo.close();
        }
 
        @Test
@@ -168,4 +178,98 @@ public class TestRepositoryTest {
                assertEquals(detached, head.getObjectId());
                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);
+       }
 }