Search in sources :

Example 1 with CommitMissingException

use of de.catma.repository.git.CommitMissingException in project catma by forTEXT.

the class JGitRepoManager method ensureLatestSubmoduleRevision.

private void ensureLatestSubmoduleRevision(DirCacheEntry baseEntry, DirCacheEntry theirEntry, String conflictingSubmodule, CredentialsProvider credentialsProvider) throws Exception {
    try (Repository submoduleRepo = SubmoduleWalk.getSubmoduleRepository(this.gitApi.getRepository(), conflictingSubmodule)) {
        Git submoduleGitApi = Git.wrap(submoduleRepo);
        boolean foundTheirs = false;
        int tries = 10;
        while (!foundTheirs && tries > 0) {
            // iterate over the revisions until we find their commit or until we reach
            // the the common ancestor version (base)
            Iterator<RevCommit> revIterator = submoduleGitApi.log().call().iterator();
            while (revIterator.hasNext()) {
                RevCommit revCommit = revIterator.next();
                if (revCommit.getId().equals(theirEntry.getObjectId())) {
                    // we found their version
                    foundTheirs = true;
                    break;
                } else if (revCommit.getId().equals(baseEntry.getObjectId())) {
                    // we reached the common ancestor
                    break;
                }
            }
            if (!foundTheirs) {
                // we reached the common ancestor without finding
                // their commit, so we pull again to see if it comes in now
                // and then we start over
                submoduleGitApi.checkout().setName(Constants.MASTER).setCreateBranch(false).call();
                PullResult pullResult = submoduleGitApi.pull().setCredentialsProvider(credentialsProvider).call();
                if (!pullResult.isSuccessful()) {
                    throw new IllegalStateException(String.format("Trying to get the latest commits for %1$s failed!", conflictingSubmodule));
                }
                submoduleGitApi.checkout().setName(ILocalGitRepositoryManager.DEFAULT_LOCAL_DEV_BRANCH).setCreateBranch(false).call();
                submoduleGitApi.rebase().setUpstream(Constants.MASTER).call();
            }
            tries--;
        }
        if (!foundTheirs) {
            Logger.getLogger(this.getClass().getName()).severe(String.format("Cannot resolve root conflict for submodule %1$s commit %2$s is missing!", conflictingSubmodule, theirEntry.getObjectId().toString()));
            throw new CommitMissingException("Failed to synchronize the Project because of a missing commit, " + "try again later or contact the system administrator!");
        }
    }
}
Also used : CommitMissingException(de.catma.repository.git.CommitMissingException) Repository(org.eclipse.jgit.lib.Repository) Git(org.eclipse.jgit.api.Git) PullResult(org.eclipse.jgit.api.PullResult) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 2 with CommitMissingException

use of de.catma.repository.git.CommitMissingException in project catma by forTEXT.

the class JGitRepoManager method resolveRootConflicts.

@Override
public Collection<DeletedResourceConflict> resolveRootConflicts(String projectId, CredentialsProvider credentialsProvider) throws IOException {
    if (!isAttached()) {
        throw new IllegalStateException("Can't call `resolveRootConflicts` on a detached instance");
    }
    List<DeletedResourceConflict> deletedResourceConflicts = new ArrayList<>();
    DirCache dirCache = gitApi.getRepository().lockDirCache();
    try {
        if (dirCache.hasUnmergedPaths()) {
            Status status = gitApi.status().call();
            for (String conflictingSubmodule : status.getConflicting()) {
                StageState conflictState = status.getConflictingStageState().get(conflictingSubmodule);
                switch(conflictState) {
                    case BOTH_MODIFIED:
                        {
                            // get the base entry from where the branches diverge, the common ancestor version
                            int baseIdx = dirCache.findEntry(conflictingSubmodule);
                            DirCacheEntry baseEntry = dirCache.getEntry(baseIdx);
                            // get their version, the being-merged in version
                            DirCacheEntry theirEntry = dirCache.getEntry(baseIdx + 2);
                            if (theirEntry.getPathString().equals(conflictingSubmodule) && theirEntry.getStage() == 3) {
                                // we try to make sure that their version is included (merged) in the latest version
                                // of this submodule
                                ensureLatestSubmoduleRevision(baseEntry, theirEntry, conflictingSubmodule, credentialsProvider);
                                try (Repository subModuleRepo = SubmoduleWalk.getSubmoduleRepository(this.gitApi.getRepository(), conflictingSubmodule)) {
                                    // now get the current submodule revision (which includes the merge)
                                    ObjectId subModuleHeadRevision = subModuleRepo.resolve(Constants.HEAD);
                                    baseEntry.setObjectId(subModuleHeadRevision);
                                }
                                break;
                            } else {
                                Logger.getLogger(this.getClass().getName()).severe(String.format("Cannot resolve root conflict for submodule %1$s expected a 'theirs'-stage-3 commit entry but found none!", conflictingSubmodule));
                                throw new CommitMissingException("Failed to synchronize the Project because of an unexpected merge conflict, " + "please contact the system administrator!");
                            }
                        }
                    case DELETED_BY_THEM:
                        {
                            String ourTreeName = "refs/heads/master";
                            RevCommit ourCommit = gitApi.log().add(gitApi.getRepository().resolve(ourTreeName)).addPath(conflictingSubmodule).call().iterator().next();
                            String ourLastCommitMsg = ourCommit.getFullMessage();
                            String theirTreeName = "refs/remotes/origin/master";
                            RevCommit theirCommit = gitApi.log().add(gitApi.getRepository().resolve(theirTreeName)).addPath(conflictingSubmodule).call().iterator().next();
                            if (theirCommit == null) {
                                // couldn't find their commit based on the conflicting submodule path
                                // we try to find it based on the DOT_GIT_MODULES file and the resourceId in the commit message
                                Iterator<RevCommit> remoteCommitIterator = gitApi.log().add(gitApi.getRepository().resolve(theirTreeName)).addPath(Constants.DOT_GIT_MODULES).call().iterator();
                                String resourceId = conflictingSubmodule.substring(conflictingSubmodule.indexOf('/') + 1);
                                while (remoteCommitIterator.hasNext()) {
                                    RevCommit revCommit = remoteCommitIterator.next();
                                    if (revCommit.getFullMessage().contains(resourceId)) {
                                        theirCommit = revCommit;
                                        break;
                                    }
                                }
                            }
                            String theirLastCommitMsg = "no commit found";
                            if (theirCommit != null) {
                                theirLastCommitMsg = theirCommit.getFullMessage();
                            }
                            deletedResourceConflicts.add(new DeletedResourceConflict(projectId, conflictingSubmodule, ourCommit.getName(), ourLastCommitMsg, theirCommit != null ? theirCommit.getName() : "", theirLastCommitMsg, theirCommit != null ? theirCommit.getCommitterIdent().getName() : "", true));
                            break;
                        }
                    case DELETED_BY_US:
                        {
                            String ourTreeName = "refs/heads/master";
                            RevCommit ourCommit = gitApi.log().add(gitApi.getRepository().resolve(ourTreeName)).addPath(conflictingSubmodule).call().iterator().next();
                            String ourLastCommitMsg = ourCommit.getFullMessage();
                            String theirTreeName = "refs/remotes/origin/master";
                            RevCommit theirCommit = gitApi.log().add(gitApi.getRepository().resolve(theirTreeName)).addPath(conflictingSubmodule).call().iterator().next();
                            String theirLastCommitMsg = theirCommit.getFullMessage();
                            deletedResourceConflicts.add(new DeletedResourceConflict(projectId, conflictingSubmodule, ourCommit.getName(), ourLastCommitMsg, theirCommit.getName(), theirLastCommitMsg, theirCommit.getCommitterIdent().getName(), false));
                            break;
                        }
                    default:
                        {
                            Logger.getLogger(this.getClass().getName()).severe(String.format("Cannot resolve root conflict for submodule %1$s %2$s not supported yet!", conflictingSubmodule, conflictState.name()));
                            throw new CommitMissingException("Failed to synchronize the Project because of an unexpected merge conflict, " + "please contact the system administrator!");
                        }
                }
            }
            dirCache.write();
            dirCache.commit();
        } else {
            dirCache.unlock();
        }
    } catch (Exception e) {
        try {
            dirCache.unlock();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        throw new IOException("Failed to resolve root conflicts", e);
    }
    return deletedResourceConflicts;
}
Also used : Status(org.eclipse.jgit.api.Status) SubmoduleStatus(org.eclipse.jgit.submodule.SubmoduleStatus) CommitMissingException(de.catma.repository.git.CommitMissingException) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) ObjectId(org.eclipse.jgit.lib.ObjectId) DeletedResourceConflict(de.catma.project.conflict.DeletedResourceConflict) ArrayList(java.util.ArrayList) IOException(java.io.IOException) CommitMissingException(de.catma.repository.git.CommitMissingException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) IOException(java.io.IOException) NoFilepatternException(org.eclipse.jgit.api.errors.NoFilepatternException) JGitInternalException(org.eclipse.jgit.api.errors.JGitInternalException) DirCache(org.eclipse.jgit.dircache.DirCache) Repository(org.eclipse.jgit.lib.Repository) StageState(org.eclipse.jgit.lib.IndexDiff.StageState) Iterator(java.util.Iterator) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Aggregations

CommitMissingException (de.catma.repository.git.CommitMissingException)2 Repository (org.eclipse.jgit.lib.Repository)2 RevCommit (org.eclipse.jgit.revwalk.RevCommit)2 DeletedResourceConflict (de.catma.project.conflict.DeletedResourceConflict)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 Iterator (java.util.Iterator)1 Git (org.eclipse.jgit.api.Git)1 PullResult (org.eclipse.jgit.api.PullResult)1 Status (org.eclipse.jgit.api.Status)1 GitAPIException (org.eclipse.jgit.api.errors.GitAPIException)1 JGitInternalException (org.eclipse.jgit.api.errors.JGitInternalException)1 NoFilepatternException (org.eclipse.jgit.api.errors.NoFilepatternException)1 DirCache (org.eclipse.jgit.dircache.DirCache)1 DirCacheEntry (org.eclipse.jgit.dircache.DirCacheEntry)1 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)1 StageState (org.eclipse.jgit.lib.IndexDiff.StageState)1 ObjectId (org.eclipse.jgit.lib.ObjectId)1 SubmoduleStatus (org.eclipse.jgit.submodule.SubmoduleStatus)1