]> source.dussan.org Git - jgit.git/commitdiff
Add support for creating detached heads 46/146/3
authorRobin Rosenberg <robin.rosenberg@dewire.com>
Mon, 28 Dec 2009 15:49:50 +0000 (16:49 +0100)
committerShawn O. Pearce <spearce@spearce.org>
Mon, 28 Dec 2009 23:58:40 +0000 (15:58 -0800)
An extra flag when creating a RefUpdate object allows the
caller to destroy the symref and replace it with an object
ref, a.k.a. detached HEAD.

Change-Id: Ia88d48eab1eb4861ebfa39e3be9258c3824a19db
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

index fa77c6a8d2bbb0fd72c6050d1d9ab0038192e15b..d851528cdd7c347007f561a912b1765057afaccd 100644 (file)
@@ -292,6 +292,64 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
                assertEquals(pid, db.resolve("refs/heads/master"));
        }
 
+       /**
+        * Update the HEAD ref. Only it should be changed, not what it points to.
+        *
+        * @throws Exception
+        */
+       public void testUpdateRefDetached() throws Exception {
+               ObjectId pid = db.resolve("refs/heads/master");
+               ObjectId ppid = db.resolve("refs/heads/master^");
+               RefUpdate updateRef = db.updateRef("HEAD", true);
+               updateRef.setForceUpdate(true);
+               updateRef.setNewObjectId(ppid);
+               Result update = updateRef.update();
+               assertEquals(Result.FORCED, update);
+               assertEquals(ppid, db.resolve("HEAD"));
+               Ref ref = db.getRef("HEAD");
+               assertEquals("HEAD", ref.getName());
+               assertEquals("HEAD", ref.getOrigName());
+
+               // the branch HEAD referred to is left untouched
+               assertEquals(pid, db.resolve("refs/heads/master"));
+               ReflogReader reflogReader = new  ReflogReader(db, "HEAD");
+               org.eclipse.jgit.lib.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
+               assertEquals(pid, e.getOldId());
+               assertEquals(ppid, e.getNewId());
+               assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
+               assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
+               assertEquals(1250379778000L, e.getWho().getWhen().getTime());
+       }
+
+       /**
+        * Update the HEAD ref when the referenced branch is unborn
+        *
+        * @throws Exception
+        */
+       public void testUpdateRefDetachedUnbornHead() throws Exception {
+               ObjectId ppid = db.resolve("refs/heads/master^");
+               db.writeSymref("HEAD", "refs/heads/unborn");
+               RefUpdate updateRef = db.updateRef("HEAD", true);
+               updateRef.setForceUpdate(true);
+               updateRef.setNewObjectId(ppid);
+               Result update = updateRef.update();
+               assertEquals(Result.NEW, update);
+               assertEquals(ppid, db.resolve("HEAD"));
+               Ref ref = db.getRef("HEAD");
+               assertEquals("HEAD", ref.getName());
+               assertEquals("HEAD", ref.getOrigName());
+
+               // the branch HEAD referred to is left untouched
+               assertNull(db.resolve("refs/heads/unborn"));
+               ReflogReader reflogReader = new  ReflogReader(db, "HEAD");
+               org.eclipse.jgit.lib.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
+               assertEquals(ObjectId.zeroId(), e.getOldId());
+               assertEquals(ppid, e.getNewId());
+               assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
+               assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
+               assertEquals(1250379778000L, e.getWho().getWhen().getTime());
+       }
+
        /**
         * Delete a ref that exists both as packed and loose. Make sure the ref
         * cannot be resolved after delete.
index 67358c808470b331069132519ff8e4ed7412a33f..fb6a27db30d8c831b83f9e2fc5f97b23188de824 100644 (file)
@@ -137,10 +137,30 @@ class RefDatabase {
         *             to the base ref, as the symbolic ref could not be read.
         */
        RefUpdate newUpdate(final String name) throws IOException {
+               return newUpdate(name, false);
+       }
+
+       /**
+        * Create a command to update, create or delete a ref in this repository.
+        *
+        * @param name
+        *            name of the ref the caller wants to modify.
+        * @param detach
+        *            true to detach the ref, i.e. replace symref with object ref
+        * @return an update command. The caller must finish populating this command
+        *         and then invoke one of the update methods to actually make a
+        *         change.
+        * @throws IOException
+        *             a symbolic ref was passed in and could not be resolved back
+        *             to the base ref, as the symbolic ref could not be read.
+        */
+       RefUpdate newUpdate(final String name, boolean detach) throws IOException {
                refreshPackedRefs();
                Ref r = readRefBasic(name, 0);
                if (r == null)
                        r = new Ref(Ref.Storage.NEW, name, null);
+               else if (detach)
+                       r = new Ref(Ref.Storage.NEW, name, r.getObjectId());
                return new RefUpdate(this, r, fileForRef(r.getName()));
        }
 
index 5b8b34fa6aac37747502cdf28b2334f7e1478443..f576b057ca62500ebd46b616c3b6c75e9de38371 100644 (file)
@@ -501,6 +501,24 @@ public class Repository {
                return refs.newUpdate(ref);
        }
 
+       /**
+        * Create a command to update, create or delete a ref in this repository.
+        *
+        * @param ref
+        *            name of the ref the caller wants to modify.
+        * @param detach
+        *            true to create a detached head
+        * @return an update command. The caller must finish populating this command
+        *         and then invoke one of the update methods to actually make a
+        *         change.
+        * @throws IOException
+        *             a symbolic ref was passed in and could not be resolved back
+        *             to the base ref, as the symbolic ref could not be read.
+        */
+       public RefUpdate updateRef(final String ref, final boolean detach) throws IOException {
+               return refs.newUpdate(ref, detach);
+       }
+
        /**
         * Create a command to rename a ref in this repository
         *