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.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.util.containers.Convertor;
|
import com.intellij.util.containers.Convertor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ObjectsConvertor {
|
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) {
|
public static List<VirtualFile> fp2vf(final List<FilePath> in) {
|
||||||
return convert(in, new Convertor<FilePath, VirtualFile>() {
|
return convert(in, FILEPATH_TO_VIRTUAL);
|
||||||
public VirtualFile convert(final FilePath fp) {
|
|
||||||
return fp.getVirtualFile();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<FilePath> vf2fp(final List<VirtualFile> in) {
|
public static List<FilePath> vf2fp(final List<VirtualFile> in) {
|
||||||
return convert(in, new Convertor<VirtualFile, FilePath>() {
|
return convert(in, VIRTUAL_FILEPATH);
|
||||||
public FilePath convert(final VirtualFile vf) {
|
|
||||||
return new FilePathImpl(vf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>();
|
final List<S> out = new ArrayList<S>();
|
||||||
for (T t : in) {
|
for (T t : in) {
|
||||||
out.add(convertor.convert(t));
|
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() {
|
public void markEverythingDirty() {
|
||||||
if (myProject.isDisposed()) return;
|
if (myProject.isDisposed()) return;
|
||||||
|
|
||||||
final boolean done = myLife.doIfAlive(new Runnable() {
|
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
myDirtBuilder.everythingDirty();
|
myDirtBuilder.everythingDirty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (done) {
|
if (lifeDrop.isDone() && (! lifeDrop.isSuspened())) {
|
||||||
myChangeListManager.scheduleUpdate();
|
myChangeListManager.scheduleUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,17 +128,20 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean takeDirt(final Consumer<DirtBuilder> filler) {
|
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() {
|
public void run() {
|
||||||
filler.consume(myDirtBuilder);
|
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();
|
myChangeListManager.scheduleUpdate();
|
||||||
}
|
}
|
||||||
// no sence in checking correct here any more: vcs is searched for asynchronously
|
// 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) {
|
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() {
|
public VcsInvalidated retrieveScopes() {
|
||||||
final Ref<DirtBuilder> dirtCopyRef = new Ref<DirtBuilder>();
|
final Ref<DirtBuilder> dirtCopyRef = new Ref<DirtBuilder>();
|
||||||
|
|
||||||
final boolean done = myLife.doIfAlive(new Runnable() {
|
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
dirtCopyRef.set(new DirtBuilder(myDirtBuilder));
|
dirtCopyRef.set(new DirtBuilder(myDirtBuilder));
|
||||||
myDirtBuilder.reset();
|
myDirtBuilder.reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (done && (! dirtCopyRef.isNull())) {
|
if (lifeDrop.isDone() && (! dirtCopyRef.isNull())) {
|
||||||
return ApplicationManager.getApplication().runReadAction(new Computable<VcsInvalidated>() {
|
return ApplicationManager.getApplication().runReadAction(new Computable<VcsInvalidated>() {
|
||||||
public VcsInvalidated compute() {
|
public VcsInvalidated compute() {
|
||||||
final Scopes scopes = new Scopes(myProject, myGuess);
|
final Scopes scopes = new Scopes(myProject, myGuess);
|
||||||
@@ -201,6 +220,23 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
|||||||
return null;
|
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 {
|
private class MyVfsListener extends VirtualFileAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void contentsChanged(VirtualFileEvent event) {
|
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 static class SynchronizedLife {
|
||||||
private LifeStages myStage;
|
private LifeStages myStage;
|
||||||
private final Object myLock;
|
private final Object myLock;
|
||||||
|
private boolean mySuspended;
|
||||||
|
|
||||||
private SynchronizedLife() {
|
private SynchronizedLife() {
|
||||||
myStage = LifeStages.NOT_BORN;
|
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
|
// allow work under inner lock: inner class, not wide scope
|
||||||
public boolean doIfAlive(final Runnable runnable) {
|
public LifeDrop doIfAlive(final Runnable runnable) {
|
||||||
synchronized (myLock) {
|
synchronized (myLock) {
|
||||||
if (LifeStages.ALIVE.equals(myStage)) {
|
if (LifeStages.ALIVE.equals(myStage)) {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
return true;
|
return new LifeDrop(true, mySuspended);
|
||||||
}
|
}
|
||||||
|
return new LifeDrop(false, mySuspended);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static enum LifeStages {
|
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.AbstractVcsAction;
|
||||||
import com.intellij.openapi.vcs.actions.VcsContext;
|
import com.intellij.openapi.vcs.actions.VcsContext;
|
||||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
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.CommittedChangesAdapter;
|
||||||
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
|
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
|
||||||
import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager;
|
import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager;
|
||||||
@@ -305,11 +306,13 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
|||||||
|
|
||||||
// vcs name, context object
|
// vcs name, context object
|
||||||
private final Map<String, SequentialUpdatesContext> myContextInfo;
|
private final Map<String, SequentialUpdatesContext> myContextInfo;
|
||||||
|
private VcsDirtyScopeManager myDirtyScopeManager;
|
||||||
|
|
||||||
public Updater(final Project project, final FilePath[] roots, final Map<AbstractVcs, Collection<FilePath>> vcsToVirtualFiles) {
|
public Updater(final Project project, final FilePath[] roots, final Map<AbstractVcs, Collection<FilePath>> vcsToVirtualFiles) {
|
||||||
super(project, getTemplatePresentation().getText(), true, VcsConfiguration.getInstance(project).getUpdateOption());
|
super(project, getTemplatePresentation().getText(), true, VcsConfiguration.getInstance(project).getUpdateOption());
|
||||||
myProject = project;
|
myProject = project;
|
||||||
myProjectLevelVcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project);
|
myProjectLevelVcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project);
|
||||||
|
myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||||
myRoots = roots;
|
myRoots = roots;
|
||||||
myVcsToVirtualFiles = vcsToVirtualFiles;
|
myVcsToVirtualFiles = vcsToVirtualFiles;
|
||||||
|
|
||||||
@@ -329,7 +332,36 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
|||||||
++ myUpdateNumber;
|
++ 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) {
|
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();
|
ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges();
|
||||||
myProjectLevelVcsManager.startBackgroundVcsOperation();
|
myProjectLevelVcsManager.startBackgroundVcsOperation();
|
||||||
ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
|
ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
|
||||||
@@ -405,6 +437,14 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
|
try {
|
||||||
|
onSuccessImpl();
|
||||||
|
} finally {
|
||||||
|
releaseIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSuccessImpl() {
|
||||||
if (myProject.isDisposed()) {
|
if (myProject.isDisposed()) {
|
||||||
ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges();
|
ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges();
|
||||||
return;
|
return;
|
||||||
@@ -423,7 +463,6 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (myActionInfo.canChangeFileStatus()) {
|
if (myActionInfo.canChangeFileStatus()) {
|
||||||
final VcsDirtyScopeManager myManager = VcsDirtyScopeManager.getInstance(myProject);
|
|
||||||
final List<VirtualFile> files = new ArrayList<VirtualFile>();
|
final List<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||||
UpdateFilesHelper.iterateFileGroupFiles(myUpdatedFiles, new UpdateFilesHelper.Callback() {
|
UpdateFilesHelper.iterateFileGroupFiles(myUpdatedFiles, new UpdateFilesHelper.Callback() {
|
||||||
public void onFile(final String filePath, final String groupId) {
|
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());
|
final boolean updateSuccess = (! someSessionWasCancelled) && (myVcsExceptions.isEmpty());
|
||||||
|
|||||||
Reference in New Issue
Block a user