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);
}
}
}
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;
}
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();
}
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;
}
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;
}
Aggregations