Skip to content
Snippets Groups Projects
Commit 5b13adce authored by Robin Rosenberg's avatar Robin Rosenberg Committed by Shawn O. Pearce
Browse files

Add support for creating detached heads


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: default avatarRobin Rosenberg <robin.rosenberg@dewire.com>
Signed-off-by: default avatarShawn O. Pearce <spearce@spearce.org>
parent 1ec393e7
No related branches found
No related tags found
No related merge requests found
......@@ -292,6 +292,64 @@ public void testUpdateRefForward() throws IOException {
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.
......
......@@ -137,10 +137,30 @@ ObjectId idOf(final String name) throws IOException {
* 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()));
}
......
......@@ -501,6 +501,24 @@ public RefUpdate updateRef(final String ref) throws IOException {
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
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment