Search in sources :

Example 76 with GitRepository

use of git4idea.repo.GitRepository in project intellij-community by JetBrains.

the class GitRebaseProcess method rebaseSingleRoot.

@NotNull
private GitRebaseStatus rebaseSingleRoot(@NotNull GitRepository repository, @Nullable GitRebaseResumeMode customMode, @NotNull Map<GitRepository, GitSuccessfulRebase> alreadyRebased) {
    VirtualFile root = repository.getRoot();
    String repoName = getShortRepositoryName(repository);
    LOG.info("Rebasing root " + repoName + ", mode: " + notNull(customMode, "standard"));
    Collection<GitRebaseUtils.CommitInfo> skippedCommits = newArrayList();
    MultiMap<GitRepository, GitRebaseUtils.CommitInfo> allSkippedCommits = getSkippedCommits(alreadyRebased);
    boolean retryWhenDirty = false;
    while (true) {
        GitRebaseProblemDetector rebaseDetector = new GitRebaseProblemDetector();
        GitUntrackedFilesOverwrittenByOperationDetector untrackedDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root);
        GitRebaseLineListener progressListener = new GitRebaseLineListener();
        GitCommandResult result = callRebase(repository, customMode, rebaseDetector, untrackedDetector, progressListener);
        boolean somethingRebased = customMode != null || progressListener.getResult().current > 1;
        if (result.success()) {
            if (rebaseDetector.hasStoppedForEditing()) {
                showStoppedForEditingMessage(repository);
                return new GitRebaseStatus(GitRebaseStatus.Type.SUSPENDED, skippedCommits);
            }
            LOG.debug("Successfully rebased " + repoName);
            return GitSuccessfulRebase.parseFromOutput(result.getOutput(), skippedCommits);
        } else if (result.cancelled()) {
            LOG.info("Rebase was cancelled");
            throw new ProcessCanceledException();
        } else if (rebaseDetector.isDirtyTree() && customMode == null && !retryWhenDirty) {
            // if the initial dirty tree check doesn't find all local changes, we are still ready to stash-on-demand,
            // but only once per repository (if the error happens again, that means that the previous stash attempt failed for some reason),
            // and not in the case of --continue (where all local changes are expected to be committed) or --skip.
            LOG.debug("Dirty tree detected in " + repoName);
            String saveError = saveLocalChanges(singleton(repository.getRoot()));
            if (saveError == null) {
                // try same repository again
                retryWhenDirty = true;
            } else {
                LOG.warn("Couldn't " + mySaver.getOperationName() + " root " + repository.getRoot() + ": " + saveError);
                showFatalError(saveError, repository, somethingRebased, alreadyRebased.keySet(), allSkippedCommits);
                GitRebaseStatus.Type type = somethingRebased ? GitRebaseStatus.Type.SUSPENDED : GitRebaseStatus.Type.ERROR;
                return new GitRebaseStatus(type, skippedCommits);
            }
        } else if (untrackedDetector.wasMessageDetected()) {
            LOG.info("Untracked files detected in " + repoName);
            showUntrackedFilesError(untrackedDetector.getRelativeFilePaths(), repository, somethingRebased, alreadyRebased.keySet(), allSkippedCommits);
            GitRebaseStatus.Type type = somethingRebased ? GitRebaseStatus.Type.SUSPENDED : GitRebaseStatus.Type.ERROR;
            return new GitRebaseStatus(type, skippedCommits);
        } else if (rebaseDetector.isNoChangeError()) {
            LOG.info("'No changes' situation detected in " + repoName);
            GitRebaseUtils.CommitInfo currentRebaseCommit = GitRebaseUtils.getCurrentRebaseCommit(myProject, root);
            if (currentRebaseCommit != null)
                skippedCommits.add(currentRebaseCommit);
            customMode = GitRebaseResumeMode.SKIP;
        } else if (rebaseDetector.isMergeConflict()) {
            LOG.info("Merge conflict in " + repoName);
            ResolveConflictResult resolveResult = showConflictResolver(repository, false);
            if (resolveResult == ResolveConflictResult.ALL_RESOLVED) {
                customMode = GitRebaseResumeMode.CONTINUE;
            } else if (resolveResult == ResolveConflictResult.NOTHING_TO_MERGE) {
                // the output is the same for the cases:
                // (1) "unresolved conflicts"
                // (2) "manual editing of a file not followed by `git add`
                // => we check if there are any unresolved conflicts, and if not, then it is the case #2 which we are not handling
                LOG.info("Unmerged changes while rebasing root " + repoName + ": " + result.getErrorOutputAsJoinedString());
                showFatalError(result.getErrorOutputAsHtmlString(), repository, somethingRebased, alreadyRebased.keySet(), allSkippedCommits);
                GitRebaseStatus.Type type = somethingRebased ? GitRebaseStatus.Type.SUSPENDED : GitRebaseStatus.Type.ERROR;
                return new GitRebaseStatus(type, skippedCommits);
            } else {
                notifyNotAllConflictsResolved(repository, allSkippedCommits);
                return new GitRebaseStatus(GitRebaseStatus.Type.SUSPENDED, skippedCommits);
            }
        } else {
            LOG.info("Error rebasing root " + repoName + ": " + result.getErrorOutputAsJoinedString());
            showFatalError(result.getErrorOutputAsHtmlString(), repository, somethingRebased, alreadyRebased.keySet(), allSkippedCommits);
            GitRebaseStatus.Type type = somethingRebased ? GitRebaseStatus.Type.SUSPENDED : GitRebaseStatus.Type.ERROR;
            return new GitRebaseStatus(type, skippedCommits);
        }
    }
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) GitUntrackedFilesOverwrittenByOperationDetector(git4idea.commands.GitUntrackedFilesOverwrittenByOperationDetector) GitCommandResult(git4idea.commands.GitCommandResult) GitRepository(git4idea.repo.GitRepository) SuccessType(git4idea.rebase.GitSuccessfulRebase.SuccessType) ProcessCanceledException(com.intellij.openapi.progress.ProcessCanceledException) NotNull(org.jetbrains.annotations.NotNull) ObjectUtils.assertNotNull(com.intellij.util.ObjectUtils.assertNotNull)

Example 77 with GitRepository

use of git4idea.repo.GitRepository in project intellij-community by JetBrains.

the class GitRebaseSpec method getIncompleteRepositories.

/**
   * Returns repositories for which rebase is in progress, has failed and we want to retry, or didn't start yet. <br/>
   * It is guaranteed that if there is a rebase in progress (returned by {@link #getOngoingRebase()}, it will be the first in the list.
   */
@NotNull
public List<GitRepository> getIncompleteRepositories() {
    List<GitRepository> incompleteRepositories = ContainerUtil.newArrayList();
    final GitRepository ongoingRebase = getOngoingRebase();
    if (ongoingRebase != null)
        incompleteRepositories.add(ongoingRebase);
    incompleteRepositories.addAll(DvcsUtil.sortRepositories(ContainerUtil.filter(myStatuses.keySet(), new Condition<GitRepository>() {

        @Override
        public boolean value(@NotNull GitRepository repository) {
            return !repository.equals(ongoingRebase) && myStatuses.get(repository).getType() != GitRebaseStatus.Type.SUCCESS;
        }
    })));
    return incompleteRepositories;
}
Also used : GitRepository(git4idea.repo.GitRepository) NotNull(org.jetbrains.annotations.NotNull)

Example 78 with GitRepository

use of git4idea.repo.GitRepository in project intellij-community by JetBrains.

the class GitRebaseUpdater method fastForwardMerge.

/**
   * Tries to execute {@code git merge --ff-only}.
   * @return true, if everything is successful; false for any error (to let a usual "fair" update deal with it).
   */
public boolean fastForwardMerge() {
    LOG.info("Trying fast-forward merge for " + myRoot);
    GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRoot);
    if (repository == null) {
        LOG.error("Repository is null for " + myRoot);
        return false;
    }
    try {
        markStart(myRoot);
    } catch (VcsException e) {
        LOG.info("Couldn't mark start for repository " + myRoot, e);
        return false;
    }
    GitCommandResult result = myGit.merge(repository, getRemoteBranchToMerge(), singletonList("--ff-only"));
    try {
        markEnd(myRoot);
    } catch (VcsException e) {
        // this is not critical, and update has already happened,
        // so we just notify the user about problems with collecting the updated changes.
        LOG.info("Couldn't mark end for repository " + myRoot, e);
        VcsNotifier.getInstance(myProject).notifyMinorWarning("Couldn't collect the updated files info", String.format("Update of %s was successful, but we couldn't collect the updated changes because of an error", myRoot), null);
    }
    return result.success();
}
Also used : GitRepository(git4idea.repo.GitRepository) VcsException(com.intellij.openapi.vcs.VcsException) GitCommandResult(git4idea.commands.GitCommandResult)

Example 79 with GitRepository

use of git4idea.repo.GitRepository in project intellij-community by JetBrains.

the class GitUpdateProcess method defineUpdaters.

@NotNull
private Map<VirtualFile, GitUpdater> defineUpdaters(@NotNull UpdateMethod updateMethod) throws VcsException {
    final Map<VirtualFile, GitUpdater> updaters = new HashMap<>();
    LOG.info("updateImpl: defining updaters...");
    for (GitRepository repository : myRepositories) {
        VirtualFile root = repository.getRoot();
        GitUpdater updater = GitUpdater.getUpdater(myProject, myGit, myTrackedBranches, root, myProgressIndicator, myUpdatedFiles, updateMethod);
        if (updater.isUpdateNeeded()) {
            updaters.put(root, updater);
        }
        LOG.info("update| root=" + root + " ,updater=" + updater);
    }
    return updaters;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) GitRepository(git4idea.repo.GitRepository) HashMap(java.util.HashMap) NotNull(org.jetbrains.annotations.NotNull)

Example 80 with GitRepository

use of git4idea.repo.GitRepository in project intellij-community by JetBrains.

the class GitUpdateProcess method checkTrackedBranchesConfigured.

/**
   * For each root check that the repository is on branch, and this branch is tracking a remote branch,
   * and the remote branch exists.
   * If it is not true for at least one of roots, notify and return false.
   * If branch configuration is OK for all roots, return true.
   */
private boolean checkTrackedBranchesConfigured() {
    LOG.info("checking tracked branch configuration...");
    for (GitRepository repository : myRepositories) {
        VirtualFile root = repository.getRoot();
        final GitLocalBranch branch = repository.getCurrentBranch();
        if (branch == null) {
            LOG.info("checkTrackedBranchesConfigured: current branch is null in " + repository);
            notifyImportantError(myProject, "Can't update: no current branch", "You are in 'detached HEAD' state, which means that you're not on any branch" + rootStringIfNeeded(root) + "Checkout a branch to make update possible.");
            return false;
        }
        GitBranchTrackInfo trackInfo = GitBranchUtil.getTrackInfoForBranch(repository, branch);
        if (trackInfo == null) {
            final String branchName = branch.getName();
            LOG.info(String.format("checkTrackedBranchesConfigured: no track info for current branch %s in %s", branch, repository));
            String recommendedCommand = String.format(GitVersionSpecialty.KNOWS_SET_UPSTREAM_TO.existsIn(repository.getVcs().getVersion()) ? "git branch --set-upstream-to origin/%1$s %1$s" : "git branch --set-upstream %1$s origin/%1$s", branchName);
            notifyImportantError(myProject, "Can't update: no tracked branch", "No tracked branch configured for branch " + code(branchName) + rootStringIfNeeded(root) + "To make your branch track a remote branch call, for example,<br/>" + "<code>" + recommendedCommand + "</code>");
            return false;
        }
        myTrackedBranches.put(root, new GitBranchPair(branch, trackInfo.getRemoteBranch()));
    }
    return true;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) GitRepository(git4idea.repo.GitRepository) GitLocalBranch(git4idea.GitLocalBranch) GitBranchPair(git4idea.branch.GitBranchPair) GitBranchTrackInfo(git4idea.repo.GitBranchTrackInfo)

Aggregations

GitRepository (git4idea.repo.GitRepository)123 VirtualFile (com.intellij.openapi.vfs.VirtualFile)46 NotNull (org.jetbrains.annotations.NotNull)33 Nullable (org.jetbrains.annotations.Nullable)19 Project (com.intellij.openapi.project.Project)18 GitCommandResult (git4idea.commands.GitCommandResult)14 GitRepositoryManager (git4idea.repo.GitRepositoryManager)12 VcsException (com.intellij.openapi.vcs.VcsException)11 AccessToken (com.intellij.openapi.application.AccessToken)9 File (java.io.File)8 Map (java.util.Map)8 GitRemote (git4idea.repo.GitRemote)7 FilePath (com.intellij.openapi.vcs.FilePath)6 Change (com.intellij.openapi.vcs.changes.Change)6 ProgressIndicator (com.intellij.openapi.progress.ProgressIndicator)5 Task (com.intellij.openapi.progress.Task)5 ArrayList (java.util.ArrayList)5 ObjectUtils.assertNotNull (com.intellij.util.ObjectUtils.assertNotNull)4 MultiMap (com.intellij.util.containers.MultiMap)4 GitBranch (git4idea.GitBranch)4