blob: 4890a12f5d4d306db2328c8f0d316afc84bf3e9b [file] [log] [blame]
// Copyright 2008-2010 Victor Iacoban
//
// 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 org.zmlx.hg4idea.provider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.FilePath;
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.rollback.RollbackEnvironment;
import com.intellij.openapi.vcs.rollback.RollbackProgressListener;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcsUtil.VcsFileUtil;
import org.jetbrains.annotations.NotNull;
import org.zmlx.hg4idea.HgRevisionNumber;
import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.command.HgResolveCommand;
import org.zmlx.hg4idea.command.HgRevertCommand;
import org.zmlx.hg4idea.command.HgUpdateCommand;
import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.util.HgErrorUtil;
import org.zmlx.hg4idea.util.HgUtil;
import java.io.File;
import java.util.*;
public class HgRollbackEnvironment implements RollbackEnvironment {
private final Project project;
public HgRollbackEnvironment(Project project) {
this.project = project;
}
public String getRollbackOperationName() {
return HgVcsMessages.message("hg4idea.revert");
}
public void rollbackChanges(List<Change> changes, List<VcsException> vcsExceptions,
@NotNull RollbackProgressListener listener) {
if (changes == null || changes.isEmpty()) {
return;
}
List<FilePath> toDelete = new ArrayList<FilePath>();
List<FilePath> filePaths = new LinkedList<FilePath>();
for (Change change : changes) {
ContentRevision contentRevision;
if (Change.Type.DELETED == change.getType()) {
contentRevision = change.getBeforeRevision();
}
else {
contentRevision = change.getAfterRevision();
}
if (contentRevision != null) {
filePaths.add(contentRevision.getFile());
if (Change.Type.MOVED == change.getType()) {
toDelete.add(contentRevision.getFile());
}
}
}
revert(filePaths);
for (FilePath file : toDelete) {
listener.accept(file);
try {
final File ioFile = file.getIOFile();
if (ioFile.exists()) {
if (!ioFile.delete()) {
//noinspection ThrowableInstanceNeverThrown
vcsExceptions.add(new VcsException("Unable to delete file: " + file));
}
}
}
catch (Exception e) {
//noinspection ThrowableInstanceNeverThrown
vcsExceptions.add(new VcsException("Unable to delete file: " + file, e));
}
}
}
public void rollbackMissingFileDeletion(List<FilePath> files,
List<VcsException> exceptions, RollbackProgressListener listener) {
revert(files);
}
public void rollbackModifiedWithoutCheckout(List<VirtualFile> files,
List<VcsException> exceptions, RollbackProgressListener listener) {
}
public List<VcsException> rollbackMissingFileDeletion(List<FilePath> files) {
if (files == null || files.isEmpty()) {
return null;
}
revert(files);
return null;
}
public void rollbackIfUnchanged(VirtualFile file) {
}
private void revert(@NotNull List<FilePath> filePaths) {
for (Map.Entry<VirtualFile, Collection<FilePath>> entry : HgUtil.groupFilePathsByHgRoots(project, filePaths).entrySet()) {
final VirtualFile repo = entry.getKey();
final Collection<FilePath> files = entry.getValue();
HgRevisionNumber revisionNumber = new HgWorkingCopyRevisionsCommand(project).firstParent(repo);
for (List<String> chunk : VcsFileUtil.chunkPaths(repo, files)) {
HgCommandResult revertResult = new HgRevertCommand(project).execute(repo, chunk, revisionNumber, false);
if (HgErrorUtil.hasUncommittedChangesConflict(revertResult)) {
String message = String.format("<html>Revert failed due to uncommitted merge.<br>" +
"Would you like to discard all changes for repository <it><b>%s</b></it>?</html>",
repo.getPresentableName());
int exitCode = HgUpdateCommand.showDiscardChangesConfirmation(project, message);
if (exitCode == Messages.OK) {
//discard all changes for this repository//
HgUpdateCommand updateCommand = new HgUpdateCommand(project, repo);
updateCommand.setClean(true);
updateCommand.setRevision(".");
updateCommand.execute();
}
break;
}
new HgResolveCommand(project).markResolved(repo, files);
}
}
}
}