Update via rebase always needs clean working tree.
Update via merge can be performed on a dirty working tree, if local changes don't intersect with remote changes.
GitUpdateProcess: before update ask each updater if save is needed.
GitMergeUpdater performs 'git fetch' and analyzes which files would change.
GitMergeUpdater.update is changed to make 'git merge' instead of 'git pull'.
--- /dev/null
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.branch;
+
+import git4idea.GitBranch;
+
+/**
+ * Holder for branch and its tracked branch (if any).
+ *
+ * @author Kirill Likhodedov
+ */
+public class GitBranchPair {
+ private GitBranch myBranch;
+ private GitBranch myTrackedName;
+
+ public GitBranchPair(GitBranch branch, GitBranch tracked) {
+ myBranch = branch;
+ myTrackedName = tracked;
+ }
+
+ public GitBranch getBranch() {
+ return myBranch;
+ }
+
+ public GitBranch getTracked() {
+ return myTrackedName;
+ }
+
+}
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.UIUtil;
import git4idea.GitVcs;
import git4idea.config.GitVcsSettings;
import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.util.Collection;
/**
* Saves local changes in stash or in shelf.
+ * @param rootsToSave Save changes only from these roots.
*/
- public void saveLocalChanges() throws VcsException {
+ public void saveLocalChanges(@Nullable Collection<VirtualFile> rootsToSave) throws VcsException {
+ if (rootsToSave == null || rootsToSave.isEmpty()) {
+ return;
+ }
myChangeLists = myChangeManager.getChangeListsCopy();
- save();
+ save(rootsToSave);
}
/**
}
}
+ public List<LocalChangeList> getChangeLists() {
+ return myChangeLists == null ? myChangeManager.getChangeLists() : myChangeLists;
+ }
+
+ /**
+ * Utility method - gets {@link FilePath}s of changed files in a single collection.
+ */
+ public Collection<FilePath> getChangedFiles() {
+ final HashSet<FilePath> files = new HashSet<FilePath>();
+ for (LocalChangeList changeList : getChangeLists()) {
+ for (Change c : changeList.getChanges()) {
+ if (c.getAfterRevision() != null) {
+ files.add(c.getAfterRevision().getFile());
+ }
+ if (c.getBeforeRevision() != null) {
+ files.add(c.getBeforeRevision().getFile());
+ }
+ }
+ }
+ return files;
+ }
+
/**
* Saves local changes - specific for chosen save strategy.
+ * @param rootsToSave local changes should be saved on these roots.
*/
- protected abstract void save() throws VcsException;
+ protected abstract void save(Collection<VirtualFile> rootsToSave) throws VcsException;
/**
* Loads the changes - specific for chosen save strategy.
*/
protected abstract void showSavedChanges();
- /**
- * Utility method - gets {@link FilePath}s of changed files in a single collection.
- */
- protected Collection<FilePath> getChangedFiles() {
- final HashSet<FilePath> files = new HashSet<FilePath>();
- for (LocalChangeList changeList : myChangeLists) {
- for (Change c : changeList.getChanges()) {
- if (c.getAfterRevision() != null) {
- files.add(c.getAfterRevision().getFile());
- }
- if (c.getBeforeRevision() != null) {
- files.add(c.getBeforeRevision().getFile());
- }
- }
- }
- return files;
- }
-
// Move files back to theirs change lists
private void restoreChangeLists() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
myChangeManager.invokeAfterUpdate(new Runnable() {
public void run() {
+ if (myChangeLists == null) {
+ return;
+ }
for (LocalChangeList changeList : myChangeLists) {
final Collection<Change> changes = changeList.getChanges();
LOG.debug(
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
-import git4idea.GitVcs;
+import git4idea.GitUtil;
+import git4idea.branch.GitBranchPair;
import git4idea.commands.*;
import git4idea.merge.GitMergeConflictResolver;
import git4idea.merge.GitMerger;
import git4idea.ui.GitUIUtil;
+import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
/**
public class GitMergeUpdater extends GitUpdater {
private static final Logger LOG = Logger.getInstance(GitMergeUpdater.class);
- private GitVcs myVcs;
+ private final GitUpdateProcess myUpdateProcess;
private enum MergeError {
CONFLICT,
OTHER
}
- public GitMergeUpdater(Project project, VirtualFile root, ProgressIndicator progressIndicator, UpdatedFiles updatedFiles) {
+ public GitMergeUpdater(Project project,
+ VirtualFile root,
+ GitUpdateProcess gitUpdateProcess,
+ ProgressIndicator progressIndicator,
+ UpdatedFiles updatedFiles) {
super(project, root, progressIndicator, updatedFiles);
- myVcs = GitVcs.getInstance(project);
+ myUpdateProcess = gitUpdateProcess;
}
@Override
protected GitUpdateResult doUpdate() {
final GitMerger merger = new GitMerger(myProject);
- final GitLineHandler pullHandler = makePullHandler(myRoot);
+ final GitLineHandler mergeHandler = makeMergeHandler(myRoot);
final AtomicReference<MergeError> mergeError = new AtomicReference<MergeError>(MergeError.OTHER);
- pullHandler.addLineListener(new GitLineHandlerAdapter() {
+ mergeHandler.addLineListener(new GitLineHandlerAdapter() {
@Override
public void onLineAvailable(String line, Key outputType) {
if (line.contains("Automatic merge failed; fix conflicts and then commit the result")) {
}
});
- final GitTask pullTask = new GitTask(myProject, pullHandler, "git pull");
- pullTask.setExecuteResultInAwt(false);
- pullTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
+ final GitTask mergeTask = new GitTask(myProject, mergeHandler, "git merge");
+ mergeTask.setExecuteResultInAwt(false);
+ mergeTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
final AtomicReference<GitUpdateResult> updateResult = new AtomicReference<GitUpdateResult>();
- pullTask.executeInBackground(true, new GitTaskResultHandlerAdapter() {
+ mergeTask.executeInBackground(true, new GitTaskResultHandlerAdapter() {
@Override protected void onSuccess() {
updateResult.set(GitUpdateResult.SUCCESS);
}
@Override protected void onFailure() {
final MergeError error = mergeError.get();
if (error == MergeError.CONFLICT) {
- final boolean allMerged = new GitMergeConflictResolver(myProject, true, "Merge conflicts detected. Resolve them before continuing update.",
- "Can't update", "") {
- @Override protected boolean proceedIfNothingToMerge() throws VcsException {
- merger.mergeCommit(myRoot);
- return true;
- }
-
- @Override protected boolean proceedAfterAllMerged() throws VcsException {
- merger.mergeCommit(myRoot);
- return true;
- }
- }.mergeFiles(Collections.singleton(myRoot));
+ final boolean allMerged =
+ new GitMergeConflictResolver(myProject, true, "Merge conflicts detected. Resolve them before continuing update.",
+ "Can't update", "") {
+ @Override protected boolean proceedIfNothingToMerge() throws VcsException {
+ merger.mergeCommit(myRoot);
+ return true;
+ }
+
+ @Override protected boolean proceedAfterAllMerged() throws VcsException {
+ merger.mergeCommit(myRoot);
+ return true;
+ }
+ }.mergeFiles(Collections.singleton(myRoot));
updateResult.set(allMerged ? GitUpdateResult.SUCCESS : GitUpdateResult.INCOMPLETE);
} else {
- GitUIUtil.notifyImportantError(myProject, "Error merging", GitUIUtil.stringifyErrors(pullHandler.errors()));
+ GitUIUtil.notifyImportantError(myProject, "Error merging", GitUIUtil.stringifyErrors(mergeHandler.errors()));
updateResult.set(GitUpdateResult.ERROR);
}
}
return updateResult.get();
}
+ @Override
+ public boolean isSaveNeeded() {
+ boolean fetchSuccess = fetch();
+ if (!fetchSuccess) {
+ return true; // fail safe: fetch failed, will save the root.
+ }
+
+ // git log --name-status master..origin/master
+ GitBranchPair gitBranchPair = myUpdateProcess.getTrackedBranches().get(myRoot);
+ String currentBranch = gitBranchPair.getBranch().getName();
+ String remoteBranch = gitBranchPair.getTracked().getName();
+ try {
+ Collection<String> remotelyChanged = getRemotelyChangedPaths(currentBranch, remoteBranch);
+ Collection<FilePath> locallyChanged = myUpdateProcess.getSaver().getChangedFiles();
+ for (FilePath localPath : locallyChanged) {
+ if (remotelyChanged.contains(localPath.getPath())) { // found a file which was changed locally and remotely => need to save
+ return true;
+ }
+ }
+ return false;
+ } catch (VcsException e) {
+ LOG.info("failed to get remotely changed files for " + currentBranch + ".." + remoteBranch, e);
+ return true; // fail safe
+ }
+ }
+
+ /**
+ * Fetches the tracked remote for current branch.
+ * @return true if fetch was successful, false in the case of error.
+ * @param remote
+ */
+ private boolean fetch() {
+ final GitLineHandler h = new GitLineHandler(myProject, myRoot, GitCommand.FETCH);
+
+ final GitTask fetchTask = new GitTask(myProject, h, "Fetching changes...");
+ fetchTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
+ final AtomicBoolean success = new AtomicBoolean();
+ fetchTask.executeInBackground(true, new GitTaskResultHandlerAdapter() {
+ @Override protected void onSuccess() {
+ success.set(true);
+ }
+
+ @Override protected void onCancel() {
+ LOG.info("Cancelled fetch.");
+ }
+
+ @Override protected void onFailure() {
+ LOG.info("Error fetching: " + h.errors());
+ }
+ });
+ return success.get();
+ }
+
+ // git log --name-status master..origin/master
+ private @NotNull Collection<String> getRemotelyChangedPaths(String currentBranch, String remoteBranch) throws VcsException {
+ final GitSimpleHandler toPull = new GitSimpleHandler(myProject, myRoot, GitCommand.LOG);
+ toPull.addParameters("--name-only", "--pretty=format:");
+ toPull.addParameters(currentBranch + ".." + remoteBranch);
+ toPull.setNoSSH(true);
+ toPull.setStdoutSuppressed(true);
+ toPull.setStderrSuppressed(true);
+ final String output = toPull.run();
+
+ final Collection<String> remoteChanges = new HashSet<String>();
+ for (StringScanner s = new StringScanner(output); s.hasMoreData();) {
+ final String relative = s.line();
+ if (StringUtil.isEmptyOrSpaces(relative)) {
+ continue;
+ }
+ final String path = myRoot.getPath() + "/" + GitUtil.unescapePath(relative);
+ remoteChanges.add(path);
+ }
+ return remoteChanges;
+ }
+
private void cancel() {
try {
GitSimpleHandler h = new GitSimpleHandler(myProject, myRoot, GitCommand.RESET);
}
}
- protected GitLineHandler makePullHandler(VirtualFile root) {
+ private GitLineHandler makeMergeHandler(VirtualFile root) {
GitLineHandler h = new GitLineHandler(myProject, root, GitCommand.PULL);
h.addParameters("--no-rebase");
h.addParameters("--no-stat");
private static final Logger LOG = Logger.getInstance(GitRebaseUpdater.class.getName());
private final GitRebaser myRebaser;
- public GitRebaseUpdater(Project project, VirtualFile root, ProgressIndicator progressIndicator, UpdatedFiles updatedFiles) {
+ public GitRebaseUpdater(Project project,
+ VirtualFile root,
+ GitUpdateProcess gitUpdateProcess,
+ ProgressIndicator progressIndicator,
+ UpdatedFiles updatedFiles) {
super(project, root, progressIndicator, updatedFiles);
myRebaser = new GitRebaser(myProject);
}
+ @Override public boolean isSaveNeeded() {
+ return true;
+ }
+
protected GitUpdateResult doUpdate() {
final GitLineHandler pullHandler = makePullHandler(myRoot);
final GitRebaseProblemDetector rebaseConflictDetector = new GitRebaseProblemDetector();
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList;
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangesViewManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import git4idea.GitUtil;
import git4idea.i18n.GitBundle;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
/**
}
@Override
- protected void save() throws VcsException {
+ protected void save(Collection<VirtualFile> rootsToSave) throws VcsException {
ArrayList<Change> changes = new ArrayList<Change>();
for (LocalChangeList l : myChangeLists) {
- changes.addAll(l.getChanges());
+ changes.addAll(filterChangesByRoots(l.getChanges(), rootsToSave)); // adding only changes from roots which are to be saved
}
if (!changes.isEmpty()) {
myProgressIndicator.setText(GitBundle.getString("update.shelving.changes"));
@Override protected void showSavedChanges() {
myShelveViewManager.activateView(myShelvedChangeList);
}
+
+ /**
+ * Goes through the changes and returns only those of them which belong to any of the given roots,
+ * throwing away the changes which don't belong to any of the given roots.
+ */
+ private static @NotNull Collection<Change> filterChangesByRoots(@NotNull Collection<Change> changes, @NotNull Collection<VirtualFile> rootsToSave) {
+ Collection<Change> filteredChanges = new HashSet<Change>();
+ for (Change change : changes) {
+ final ContentRevision beforeRevision = change.getBeforeRevision();
+ if (beforeRevision != null) {
+ final VirtualFile root = GitUtil.getGitRootOrNull(beforeRevision.getFile());
+ if (root != null && rootsToSave.contains(root)) {
+ filteredChanges.add(change);
+ continue;
+ }
+ }
+
+ final ContentRevision afterRevision = change.getAfterRevision();
+ if (afterRevision != null) {
+ final VirtualFile root = GitUtil.getGitRootOrNull(afterRevision.getFile());
+ if (root != null && rootsToSave.contains(root)) {
+ filteredChanges.add(change);
+ }
+ }
+ }
+ return filteredChanges;
+ }
+
}
}
@Override
- protected void save() throws VcsException {
- Map<VirtualFile, Collection<Change>> changes = groupChangesByRoots();
+ protected void save(Collection<VirtualFile> rootsToSave) throws VcsException {
+ Map<VirtualFile, Collection<Change>> changes = groupChangesByRoots(rootsToSave);
convertSeparatorsIfNeeded(changes);
stash(changes.keySet());
}
}
// Sort changes from myChangesLists by their git roots.
- private Map<VirtualFile, Collection<Change>> groupChangesByRoots() {
+ // And use only supplied roots, ignoring changes from other roots.
+ private Map<VirtualFile, Collection<Change>> groupChangesByRoots(Collection<VirtualFile> rootsToSave) {
final Map<VirtualFile, Collection<Change>> sortedChanges = new HashMap<VirtualFile, Collection<Change>>();
for (LocalChangeList l : myChangeLists) {
final Collection<Change> changeCollection = l.getChanges();
for (Change c : changeCollection) {
if (c.getAfterRevision() != null) {
- storeChangeInMap(sortedChanges, c, c.getAfterRevision());
+ storeChangeInMap(sortedChanges, c, c.getAfterRevision(), rootsToSave);
} else if (c.getBeforeRevision() != null) {
- storeChangeInMap(sortedChanges, c, c.getBeforeRevision());
+ storeChangeInMap(sortedChanges, c, c.getBeforeRevision(), rootsToSave);
}
}
}
return sortedChanges;
}
- private static void storeChangeInMap(Map<VirtualFile, Collection<Change>> sortedChanges, Change c, ContentRevision before) {
- final VirtualFile root = GitUtil.getGitRootOrNull(before.getFile());
- if (root != null) {
+ private static void storeChangeInMap(Map<VirtualFile, Collection<Change>> sortedChanges,
+ Change c,
+ ContentRevision contentRevision,
+ Collection<VirtualFile> rootsToSave) {
+ final VirtualFile root = GitUtil.getGitRootOrNull(contentRevision.getFile());
+ if (root != null && rootsToSave.contains(root)) {
Collection<Change> changes = sortedChanges.get(root);
if (changes == null) {
changes = new ArrayList<Change>();
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.util.Clock;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.text.DateFormatUtil;
import git4idea.GitBranch;
-import git4idea.GitVcs;
+import git4idea.branch.GitBranchPair;
import git4idea.merge.GitMergeConflictResolver;
import git4idea.merge.GitMergeUtil;
import git4idea.merge.GitMerger;
import git4idea.rebase.GitRebaser;
-import java.util.Collection;
-import java.util.Set;
+import java.util.*;
import static git4idea.ui.GitUIUtil.notifyError;
import static git4idea.ui.GitUIUtil.notifyImportantError;
private final Set<VirtualFile> myRoots;
private final UpdatedFiles myUpdatedFiles;
private final ProgressIndicator myProgressIndicator;
- private final GitVcs myVcs;
- private final AbstractVcsHelper myVcsHelper;
private final GitMerger myMerger;
+ private final GitChangesSaver mySaver;
+
+ private final Map<VirtualFile, GitBranchPair> myTrackedBranches = new HashMap<VirtualFile, GitBranchPair>();
public GitUpdateProcess(Project project,
ProgressIndicator progressIndicator,
myUpdatedFiles = updatedFiles;
myProgressIndicator = progressIndicator;
myProjectManager = ProjectManagerEx.getInstanceEx();
- myVcs = GitVcs.getInstance(myProject);
- myVcsHelper = AbstractVcsHelper.getInstance(project);
myMerger = new GitMerger(myProject);
+ mySaver = GitChangesSaver.getSaver(myProject, myProgressIndicator,
+ "Uncommitted changes before update operation at " + DateFormatUtil.formatDateTime(Clock.getTime()));
}
/**
*/
public boolean update() {
LOG.info("update started");
- final GitChangesSaver saver = GitChangesSaver.getSaver(myProject, myProgressIndicator,
- "Uncommitted changes before update operation at " + DateFormatUtil.formatDateTime(Clock.getTime()));
myProjectManager.blockReloadingProjectOnExternalChanges();
try {
// check if update is possible
if (checkRebaseInProgress() || checkMergeInProgress() || checkUnmergedFiles()) { return false; }
- if (!allTrackedBranchesConfigured()) { return false; }
+ if (!checkTrackedBranchesConfigured()) { return false; }
+
+ // define updaters for each root
+ Collection<VirtualFile> rootsToSave = new HashSet<VirtualFile>(1);
+ for (VirtualFile root : myRoots) {
+ final GitUpdater updater = GitUpdater.getUpdater(myProject, this, root, myProgressIndicator, myUpdatedFiles);
+ if (updater.isSaveNeeded()) {
+ rootsToSave.add(root);
+ }
+ }
+
+ mySaver.saveLocalChanges(rootsToSave);
- saver.saveLocalChanges();
// update each root
boolean incomplete = false;
boolean success = true;
for (final VirtualFile root : myRoots) {
try {
- final GitUpdater updater = GitUpdater.getUpdater(myProject, root, myProgressIndicator, myUpdatedFiles);
+ final GitUpdater updater = GitUpdater.getUpdater(myProject, this, root, myProgressIndicator, myUpdatedFiles);
GitUpdateResult res = updater.update();
if (res == GitUpdateResult.INCOMPLETE) {
incomplete = true;
} finally {
try {
if (!incomplete) {
- saver.restoreLocalChanges();
+ mySaver.restoreLocalChanges();
} else {
- saver.notifyLocalChangesAreNotRestored();
+ mySaver.notifyLocalChangesAreNotRestored();
}
} catch (VcsException e) {
LOG.info("Couldn't restore local changes after update", e);
} catch (VcsException e) {
LOG.info("Couldn't save local changes", e);
notifyError(myProject, "Couldn't save local changes",
- "Tried to save uncommitted changes in " + saver.getSaverName() + " before update, but failed with an error.<br/>" +
+ "Tried to save uncommitted changes in " + mySaver.getSaverName() + " before update, but failed with an error.<br/>" +
"Update was cancelled.", true, e);
} finally {
myProjectManager.unblockReloadingProjectOnExternalChanges();
return false;
}
+ public Map<VirtualFile, GitBranchPair> getTrackedBranches() {
+ return myTrackedBranches;
+ }
+
+ public GitChangesSaver getSaver() {
+ return mySaver;
+ }
+
/**
* For each root check that the repository is on branch, and this branch is tracking a remote branch.
* 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 allTrackedBranchesConfigured() {
+ private boolean checkTrackedBranchesConfigured() {
for (VirtualFile root : myRoots) {
try {
final GitBranch branch = GitBranch.current(myProject, root);
"Checkout a branch to make update possible.");
return false;
}
- final String value = branch.getTrackedRemoteName(myProject, root);
- if (StringUtil.isEmpty(value)) {
+ final GitBranch tracked = branch.tracked(myProject, root);
+ if (tracked == null) {
final String branchName = branch.getName();
notifyImportantError(myProject, "Can't update: no tracked branch",
"No tracked branch configured for branch " + branchName +
"<code>git branch --set-upstream " + branchName + " origin/" + branchName + "</code>");
return false;
}
+ myTrackedBranches.put(root, new GitBranchPair(branch, tracked));
} catch (VcsException e) {
notifyImportantError(myProject, "Can't update: error identifying tracked branch", e.getLocalizedMessage());
return false;
/**
* Returns proper updater based on the update policy (merge or rebase) selected by user or stored in his .git/config
*
+ *
+ * @param gitUpdateProcess
* @param root
* @param progressIndicator
* @return {@link GitMergeUpdater} or {@link GitRebaseUpdater}.
*/
- public static GitUpdater getUpdater(Project project, VirtualFile root, ProgressIndicator progressIndicator, UpdatedFiles updatedFiles) {
+ public static GitUpdater getUpdater(Project project,
+ GitUpdateProcess gitUpdateProcess,
+ VirtualFile root,
+ ProgressIndicator progressIndicator,
+ UpdatedFiles updatedFiles) {
final GitVcsSettings settings = GitVcsSettings.getInstance(project);
if (settings == null) {
- return getDefaultUpdaterForBranch(project, root, progressIndicator, updatedFiles);
+ return getDefaultUpdaterForBranch(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
}
switch (settings.getUpdateType()) {
case REBASE:
- return new GitRebaseUpdater(project, root, progressIndicator, updatedFiles);
+ return new GitRebaseUpdater(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
case MERGE:
- return new GitMergeUpdater(project, root, progressIndicator, updatedFiles);
+ return new GitMergeUpdater(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
case BRANCH_DEFAULT:
// use default for the branch
- return getDefaultUpdaterForBranch(project, root, progressIndicator, updatedFiles);
+ return getDefaultUpdaterForBranch(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
}
- return getDefaultUpdaterForBranch(project, root, progressIndicator, updatedFiles);
+ return getDefaultUpdaterForBranch(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
}
- private static GitUpdater getDefaultUpdaterForBranch(Project project, VirtualFile root, ProgressIndicator progressIndicator, UpdatedFiles updatedFiles) {
+ private static GitUpdater getDefaultUpdaterForBranch(Project project,
+ VirtualFile root,
+ GitUpdateProcess gitUpdateProcess,
+ ProgressIndicator progressIndicator,
+ UpdatedFiles updatedFiles) {
try {
final GitBranch branchName = GitBranch.current(project, root);
final String rebase = GitConfigUtil.getValue(project, root, "branch." + branchName + ".rebase");
if (rebase != null && rebase.equalsIgnoreCase("true")) {
- return new GitRebaseUpdater(project, root, progressIndicator, updatedFiles);
+ return new GitRebaseUpdater(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
}
} catch (VcsException e) {
LOG.info("getDefaultUpdaterForBranch branch", e);
}
- return new GitMergeUpdater(project, root, progressIndicator, updatedFiles);
+ return new GitMergeUpdater(project, root, gitUpdateProcess, progressIndicator, updatedFiles);
}
public GitUpdateResult update() throws VcsException {
}
}
+ /**
+ * Checks the repository if local changes need to be saved before update.
+ * For rebase local changes need to be saved always, for merge - only in the case if merge affects the same files.
+ * @return true if local changes from this root need to be saved, false if not.
+ */
+ public abstract boolean isSaveNeeded();
+
/**
* Performs update (via rebase or merge - depending on the implementing classes).
*/