mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
VCS: refresh of local changes is buffered while updating; SVN: dirty scope is merged in case of single dirty files + no "java.io.File list" to fetch files under dirty dir; svnkit: build 1.2.x next-after-5664
This commit is contained in:
@@ -3,27 +3,43 @@ package com.intellij.openapi.vcs;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ObjectsConvertor {
|
||||
private static final Convertor<FilePath, VirtualFile> FILEPATH_TO_VIRTUAL = new Convertor<FilePath, VirtualFile>() {
|
||||
public VirtualFile convert(FilePath fp) {
|
||||
return fp.getVirtualFile();
|
||||
}
|
||||
};
|
||||
|
||||
private static final Convertor<VirtualFile, FilePath> VIRTUAL_FILEPATH = new Convertor<VirtualFile, FilePath>() {
|
||||
public FilePath convert(VirtualFile vf) {
|
||||
return new FilePathImpl(vf);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Convertor<FilePath, File> FILEPATH_FILE = new Convertor<FilePath, File>() {
|
||||
public File convert(FilePath fp) {
|
||||
return fp.getIOFile();
|
||||
}
|
||||
};
|
||||
|
||||
public static List<VirtualFile> fp2vf(final List<FilePath> in) {
|
||||
return convert(in, new Convertor<FilePath, VirtualFile>() {
|
||||
public VirtualFile convert(final FilePath fp) {
|
||||
return fp.getVirtualFile();
|
||||
}
|
||||
});
|
||||
return convert(in, FILEPATH_TO_VIRTUAL);
|
||||
}
|
||||
|
||||
public static List<FilePath> vf2fp(final List<VirtualFile> in) {
|
||||
return convert(in, new Convertor<VirtualFile, FilePath>() {
|
||||
public FilePath convert(final VirtualFile vf) {
|
||||
return new FilePathImpl(vf);
|
||||
}
|
||||
});
|
||||
return convert(in, VIRTUAL_FILEPATH);
|
||||
}
|
||||
|
||||
public static <T,S> List<S> convert(final List<T> in, final Convertor<T,S> convertor) {
|
||||
public static List<File> fp2jiof(final Collection<FilePath> in) {
|
||||
return convert(in, FILEPATH_FILE);
|
||||
}
|
||||
|
||||
public static <T,S> List<S> convert(final Collection<T> in, final Convertor<T,S> convertor) {
|
||||
final List<S> out = new ArrayList<S>();
|
||||
for (T t : in) {
|
||||
out.add(convertor.convert(t));
|
||||
|
||||
@@ -63,16 +63,32 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
}
|
||||
}
|
||||
|
||||
public void suspendMe() {
|
||||
myLife.suspendMe();
|
||||
}
|
||||
|
||||
public void reanimate() {
|
||||
final Ref<Boolean> wasNotEmptyRef = new Ref<Boolean>();
|
||||
myLife.releaseMe(new Runnable() {
|
||||
public void run() {
|
||||
wasNotEmptyRef.set(! myDirtBuilder.isEmpty());
|
||||
}
|
||||
});
|
||||
if (Boolean.TRUE.equals(wasNotEmptyRef.get())) {
|
||||
myChangeListManager.scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void markEverythingDirty() {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
final boolean done = myLife.doIfAlive(new Runnable() {
|
||||
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
|
||||
public void run() {
|
||||
myDirtBuilder.everythingDirty();
|
||||
}
|
||||
});
|
||||
|
||||
if (done) {
|
||||
if (lifeDrop.isDone() && (! lifeDrop.isSuspened())) {
|
||||
myChangeListManager.scheduleUpdate();
|
||||
}
|
||||
}
|
||||
@@ -112,17 +128,20 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
}
|
||||
|
||||
private boolean takeDirt(final Consumer<DirtBuilder> filler) {
|
||||
final boolean done = myLife.doIfAlive(new Runnable() {
|
||||
final Ref<Boolean> wasNotEmptyRef = new Ref<Boolean>();
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
filler.consume(myDirtBuilder);
|
||||
wasNotEmptyRef.set(!myDirtBuilder.isEmpty());
|
||||
}
|
||||
});
|
||||
};
|
||||
final LifeDrop lifeDrop = myLife.doIfAlive(runnable);
|
||||
|
||||
if (done && (! myDirtBuilder.isEmpty())) {
|
||||
if (lifeDrop.isDone() && (! lifeDrop.isSuspened()) && (Boolean.TRUE.equals(wasNotEmptyRef.get()))) {
|
||||
myChangeListManager.scheduleUpdate();
|
||||
}
|
||||
// no sence in checking correct here any more: vcs is searched for asynchronously
|
||||
return (! done);
|
||||
return (! lifeDrop.isDone());
|
||||
}
|
||||
|
||||
public boolean filesDirty(@Nullable final Collection<VirtualFile> filesDirty, @Nullable final Collection<VirtualFile> dirsRecursivelyDirty) {
|
||||
@@ -182,14 +201,14 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
public VcsInvalidated retrieveScopes() {
|
||||
final Ref<DirtBuilder> dirtCopyRef = new Ref<DirtBuilder>();
|
||||
|
||||
final boolean done = myLife.doIfAlive(new Runnable() {
|
||||
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
|
||||
public void run() {
|
||||
dirtCopyRef.set(new DirtBuilder(myDirtBuilder));
|
||||
myDirtBuilder.reset();
|
||||
}
|
||||
});
|
||||
|
||||
if (done && (! dirtCopyRef.isNull())) {
|
||||
|
||||
if (lifeDrop.isDone() && (! dirtCopyRef.isNull())) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<VcsInvalidated>() {
|
||||
public VcsInvalidated compute() {
|
||||
final Scopes scopes = new Scopes(myProject, myGuess);
|
||||
@@ -201,6 +220,23 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
return null;
|
||||
}
|
||||
|
||||
private String toStringScopes(final VcsInvalidated vcsInvalidated) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("is everything dirty: ").append(vcsInvalidated.isEverythingDirty()).append(";\n");
|
||||
for (VcsDirtyScope scope : vcsInvalidated.getScopes()) {
|
||||
sb.append("|\nFiles: ");
|
||||
for (FilePath path : scope.getDirtyFiles()) {
|
||||
sb.append(path).append('\n');
|
||||
}
|
||||
sb.append("\nDirs: ");
|
||||
for (FilePath filePath : scope.getRecursivelyDirtyDirectories()) {
|
||||
sb.append(filePath).append('\n');
|
||||
}
|
||||
}
|
||||
sb.append("-------------");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private class MyVfsListener extends VirtualFileAdapter {
|
||||
@Override
|
||||
public void contentsChanged(VirtualFileEvent event) {
|
||||
@@ -267,9 +303,28 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
}
|
||||
}
|
||||
|
||||
private static class LifeDrop {
|
||||
private final boolean myDone;
|
||||
private final boolean mySuspened;
|
||||
|
||||
private LifeDrop(boolean done, boolean suspened) {
|
||||
myDone = done;
|
||||
mySuspened = suspened;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return myDone;
|
||||
}
|
||||
|
||||
public boolean isSuspened() {
|
||||
return mySuspened;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SynchronizedLife {
|
||||
private LifeStages myStage;
|
||||
private final Object myLock;
|
||||
private boolean mySuspended;
|
||||
|
||||
private SynchronizedLife() {
|
||||
myStage = LifeStages.NOT_BORN;
|
||||
@@ -288,15 +343,44 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
}
|
||||
}
|
||||
|
||||
public void suspendMe() {
|
||||
synchronized (myLock) {
|
||||
if (LifeStages.ALIVE.equals(myStage)) {
|
||||
mySuspended = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseMe(final Runnable runnable) {
|
||||
synchronized (myLock) {
|
||||
if (LifeStages.ALIVE.equals(myStage)) {
|
||||
mySuspended = false;
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LifeDrop doIfAliveAndNotSuspended(final Runnable runnable) {
|
||||
synchronized (myLock) {
|
||||
synchronized (myLock) {
|
||||
if (LifeStages.ALIVE.equals(myStage) && (! mySuspended)) {
|
||||
runnable.run();
|
||||
return new LifeDrop(true, mySuspended);
|
||||
}
|
||||
return new LifeDrop(false, mySuspended);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allow work under inner lock: inner class, not wide scope
|
||||
public boolean doIfAlive(final Runnable runnable) {
|
||||
public LifeDrop doIfAlive(final Runnable runnable) {
|
||||
synchronized (myLock) {
|
||||
if (LifeStages.ALIVE.equals(myStage)) {
|
||||
runnable.run();
|
||||
return true;
|
||||
return new LifeDrop(true, mySuspended);
|
||||
}
|
||||
return new LifeDrop(false, mySuspended);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static enum LifeStages {
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.actions.AbstractVcsAction;
|
||||
import com.intellij.openapi.vcs.actions.VcsContext;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl;
|
||||
import com.intellij.openapi.vcs.changes.committed.CommittedChangesAdapter;
|
||||
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
|
||||
import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager;
|
||||
@@ -305,11 +306,13 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
|
||||
// vcs name, context object
|
||||
private final Map<String, SequentialUpdatesContext> myContextInfo;
|
||||
private VcsDirtyScopeManager myDirtyScopeManager;
|
||||
|
||||
public Updater(final Project project, final FilePath[] roots, final Map<AbstractVcs, Collection<FilePath>> vcsToVirtualFiles) {
|
||||
super(project, getTemplatePresentation().getText(), true, VcsConfiguration.getInstance(project).getUpdateOption());
|
||||
myProject = project;
|
||||
myProjectLevelVcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project);
|
||||
myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
myRoots = roots;
|
||||
myVcsToVirtualFiles = vcsToVirtualFiles;
|
||||
|
||||
@@ -329,7 +332,36 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
++ myUpdateNumber;
|
||||
}
|
||||
|
||||
private void suspendIfNeeded() {
|
||||
if (! myActionInfo.canChangeFileStatus()) {
|
||||
// i.e. for update but not for integrate or status
|
||||
((VcsDirtyScopeManagerImpl) myDirtyScopeManager).suspendMe();
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseIfNeeded() {
|
||||
if (! myActionInfo.canChangeFileStatus()) {
|
||||
// i.e. for update but not for integrate or status
|
||||
((VcsDirtyScopeManagerImpl) myDirtyScopeManager).reanimate();
|
||||
}
|
||||
}
|
||||
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
suspendIfNeeded();
|
||||
try {
|
||||
runImpl(indicator);
|
||||
} catch (Throwable t) {
|
||||
releaseIfNeeded();
|
||||
if (t instanceof Error) {
|
||||
throw ((Error) t);
|
||||
} else if (t instanceof RuntimeException) {
|
||||
throw ((RuntimeException) t);
|
||||
}
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private void runImpl(@NotNull final ProgressIndicator indicator) {
|
||||
ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges();
|
||||
myProjectLevelVcsManager.startBackgroundVcsOperation();
|
||||
ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
@@ -405,6 +437,14 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
}
|
||||
|
||||
public void onSuccess() {
|
||||
try {
|
||||
onSuccessImpl();
|
||||
} finally {
|
||||
releaseIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSuccessImpl() {
|
||||
if (myProject.isDisposed()) {
|
||||
ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges();
|
||||
return;
|
||||
@@ -423,7 +463,6 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
}
|
||||
|
||||
if (myActionInfo.canChangeFileStatus()) {
|
||||
final VcsDirtyScopeManager myManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
final List<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
UpdateFilesHelper.iterateFileGroupFiles(myUpdatedFiles, new UpdateFilesHelper.Callback() {
|
||||
public void onFile(final String filePath, final String groupId) {
|
||||
@@ -434,7 +473,7 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
}
|
||||
}
|
||||
});
|
||||
myManager.filesDirty(files, null);
|
||||
myDirtyScopeManager.filesDirty(files, null);
|
||||
}
|
||||
|
||||
final boolean updateSuccess = (! someSessionWasCancelled) && (myVcsExceptions.isEmpty());
|
||||
|
||||
Reference in New Issue
Block a user