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: Robin Rosenberg <robin.rosenberg@dewire.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
1ec393e744
commit
5b13adcea9
|
@ -292,6 +292,64 @@ public void testUpdateRefForward() throws IOException {
|
||||||
assertEquals(pid, db.resolve("refs/heads/master"));
|
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
|
* Delete a ref that exists both as packed and loose. Make sure the ref
|
||||||
* cannot be resolved after delete.
|
* 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.
|
* to the base ref, as the symbolic ref could not be read.
|
||||||
*/
|
*/
|
||||||
RefUpdate newUpdate(final String name) throws IOException {
|
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();
|
refreshPackedRefs();
|
||||||
Ref r = readRefBasic(name, 0);
|
Ref r = readRefBasic(name, 0);
|
||||||
if (r == null)
|
if (r == null)
|
||||||
r = new Ref(Ref.Storage.NEW, name, 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()));
|
return new RefUpdate(this, r, fileForRef(r.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -501,6 +501,24 @@ public RefUpdate updateRef(final String ref) throws IOException {
|
||||||
return refs.newUpdate(ref);
|
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
|
* Create a command to rename a ref in this repository
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue