James Moger
2012-06-06 f96d3233fde0d6dc5b61690e59794d209d77ae90
Possible fix for federation branch mirroring issue (issue-86)
3 files modified
126 ■■■■ changed files
src/com/gitblit/FederationPullExecutor.java 39 ●●●● patch | view | raw | blame | history
src/com/gitblit/utils/JGitUtils.java 68 ●●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/JGitUtilsTest.java 19 ●●●●● patch | view | raw | blame | history
src/com/gitblit/FederationPullExecutor.java
@@ -33,10 +33,6 @@
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 @@
                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
src/com/gitblit/utils/JGitUtils.java
@@ -1223,6 +1223,74 @@
    }
    
    /**
     * 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.
     *
     * @param repository
tests/com/gitblit/tests/JGitUtilsTest.java
@@ -236,6 +236,25 @@
    }
    @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");
        assertTrue(JGitUtils.createOrphanBranch(repository,