@@ -33,10 +33,6 @@ import java.util.Properties; | |||
import java.util.Set; | |||
import java.util.concurrent.TimeUnit; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.ResetCommand; | |||
import org.eclipse.jgit.api.ResetCommand.ResetType; | |||
import org.eclipse.jgit.lib.Ref; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.lib.StoredConfig; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
@@ -243,25 +239,28 @@ public class FederationPullExecutor implements Runnable { | |||
if (registration.mirror) { | |||
// mirror | |||
if (fetched) { | |||
// find the first branch name that FETCH_HEAD points to | |||
List<RefModel> refs = JGitUtils.getAllRefs(r).get(commit.getId()); | |||
if (!ArrayUtils.isEmpty(refs)) { | |||
for (RefModel ref : refs) { | |||
if (ref.displayName.startsWith(org.eclipse.jgit.lib.Constants.R_REMOTES)) { | |||
newFetchHead = ref.displayName; | |||
break; | |||
} | |||
// update local branches to match the remote tracking branches | |||
for (RefModel ref : JGitUtils.getRemoteBranches(r, false, -1)) { | |||
if (ref.displayName.startsWith("origin/")) { | |||
String branch = org.eclipse.jgit.lib.Constants.R_HEADS | |||
+ ref.displayName.substring(ref.displayName.indexOf('/') + 1); | |||
String hash = ref.getReferencedObjectId().getName(); | |||
JGitUtils.setBranchRef(r, branch, hash); | |||
logger.info(MessageFormat.format(" resetting {0} of {1} to {2}", branch, | |||
repository.name, hash)); | |||
} | |||
} | |||
// reset HEAD to the FETCH_HEAD branch. | |||
// if no branch was found, reset HEAD to the commit id. | |||
Git git = new Git(r); | |||
ResetCommand reset = git.reset(); | |||
reset.setMode(ResetType.SOFT); | |||
reset.setRef(newFetchHead); | |||
Ref ref = reset.call(); | |||
String newHead; | |||
if (StringUtils.isEmpty(repository.HEAD)) { | |||
newHead = newFetchHead; | |||
} else { | |||
newHead = repository.HEAD; | |||
} | |||
JGitUtils.setHEADtoRef(r, newHead); | |||
logger.info(MessageFormat.format(" resetting HEAD of {0} to {1}", | |||
repository.name, ref.getObjectId().getName())); | |||
repository.name, newHead)); | |||
registration.updateStatus(repository, FederationPullStatus.MIRRORED); | |||
} else { | |||
// indicate no commits pulled |
@@ -1222,6 +1222,74 @@ public class JGitUtils { | |||
return false; | |||
} | |||
/** | |||
* Sets the local branch ref to point to the specified commit id. | |||
* | |||
* @param repository | |||
* @param branch | |||
* @param commitId | |||
* @return true if successful | |||
*/ | |||
public static boolean setBranchRef(Repository repository, String branch, String commitId) { | |||
String branchName = branch; | |||
if (!branchName.startsWith(Constants.R_HEADS)) { | |||
branchName = Constants.R_HEADS + branch; | |||
} | |||
try { | |||
RefUpdate refUpdate = repository.updateRef(branchName, false); | |||
refUpdate.setNewObjectId(ObjectId.fromString(commitId)); | |||
RefUpdate.Result result = refUpdate.forceUpdate(); | |||
switch (result) { | |||
case NEW: | |||
case FORCED: | |||
case NO_CHANGE: | |||
case FAST_FORWARD: | |||
return true; | |||
default: | |||
LOGGER.error(MessageFormat.format("{0} {1} update to {2} returned result {3}", | |||
repository.getDirectory().getAbsolutePath(), branchName, commitId, result)); | |||
} | |||
} catch (Throwable t) { | |||
error(t, repository, "{0} failed to set {1} to {2}", branchName, commitId); | |||
} | |||
return false; | |||
} | |||
/** | |||
* Deletes the specified branch ref. | |||
* | |||
* @param repository | |||
* @param branch | |||
* @return true if successful | |||
*/ | |||
public static boolean deleteBranchRef(Repository repository, String branch) { | |||
String branchName = branch; | |||
if (!branchName.startsWith(Constants.R_HEADS)) { | |||
branchName = Constants.R_HEADS + branch; | |||
} | |||
try { | |||
RefUpdate refUpdate = repository.updateRef(branchName, false); | |||
refUpdate.setForceUpdate(true); | |||
RefUpdate.Result result = refUpdate.delete(); | |||
switch (result) { | |||
case NEW: | |||
case FORCED: | |||
case NO_CHANGE: | |||
case FAST_FORWARD: | |||
return true; | |||
default: | |||
LOGGER.error(MessageFormat.format("{0} failed to delete to {1} returned result {2}", | |||
repository.getDirectory().getAbsolutePath(), branchName, result)); | |||
} | |||
} catch (Throwable t) { | |||
error(t, repository, "{0} failed to delete {1}", branchName); | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get the full branch and tag ref names for any potential HEAD targets. | |||
* |
@@ -235,6 +235,25 @@ public class JGitUtilsTest { | |||
repository.close(); | |||
} | |||
@Test | |||
public void testRelinkBranch() throws Exception { | |||
Repository repository = GitBlitSuite.getJGitRepository(); | |||
// create/set the branch | |||
JGitUtils.setBranchRef(repository, "refs/heads/reftest", "3b358ce514ec655d3ff67de1430994d8428cdb04"); | |||
assertEquals(1, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("3b358ce514ec655d3ff67de1430994d8428cdb04")).size()); | |||
assertEquals(null, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("755dfdb40948f5c1ec79e06bde3b0a78c352f27f"))); | |||
// reset the branch | |||
JGitUtils.setBranchRef(repository, "refs/heads/reftest", "755dfdb40948f5c1ec79e06bde3b0a78c352f27f"); | |||
assertEquals(null, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("3b358ce514ec655d3ff67de1430994d8428cdb04"))); | |||
assertEquals(1, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("755dfdb40948f5c1ec79e06bde3b0a78c352f27f")).size()); | |||
// delete the branch | |||
assertTrue(JGitUtils.deleteBranchRef(repository, "refs/heads/reftest")); | |||
repository.close(); | |||
} | |||
@Test | |||
public void testCreateOrphanedBranch() throws Exception { | |||
Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES, "orphantest"); |