mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[vcs-log] register caches invalidator for log so that Invalidate... action would remove system/vcs-log directory
1. On invalidateCaches create a "corruption.marker" in system/vcs-log. 2. Check existence of this marker before creating log storage and indexes. If marker exists, remove system/vcs-log. 3. Problem arises, however, when system/vcs-log could not be deleted. Nothing can be done here, so just display error balloon, fallback to memory storage and empty indexes. Loading log in background should be disabled in this case.
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
<logHighlighterFactory implementation="com.intellij.vcs.log.ui.IndexHighlighter$Factory"/>
|
||||
|
||||
<postStartupActivity implementation="com.intellij.vcs.log.impl.VcsProjectLog$InitLogStartupActivity"/>
|
||||
|
||||
<cachesInvalidator implementation="com.intellij.vcs.log.impl.VcsLogCachesInvalidator"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 com.intellij.vcs.log.data;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcs.log.VcsLogDetailsFilter;
|
||||
import com.intellij.vcs.log.data.index.VcsLogIndex;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class EmptyIndex implements VcsLogIndex {
|
||||
@Override
|
||||
public void scheduleIndex(boolean full) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndexed(int commit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndexed(@NotNull VirtualFile root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markForIndexing(int commit, @NotNull VirtualFile root) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFilter(@NotNull List<VcsLogDetailsFilter> filters) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Integer> filter(@NotNull List<VcsLogDetailsFilter> detailsFilters) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markCorrupted() {
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.vcs.log.data;
|
||||
|
||||
import com.intellij.ide.caches.CachesInvalidator;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -35,6 +36,8 @@ import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.index.VcsLogIndex;
|
||||
import com.intellij.vcs.log.data.index.VcsLogPersistentIndex;
|
||||
import com.intellij.vcs.log.impl.FatalErrorConsumer;
|
||||
import com.intellij.vcs.log.impl.VcsLogCachesInvalidator;
|
||||
import com.intellij.vcs.log.util.PersistentUtil;
|
||||
import com.intellij.vcs.log.util.StopWatch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -91,15 +94,30 @@ public class VcsLogData implements Disposable, VcsLogDataProvider {
|
||||
myUserRegistry = (VcsUserRegistryImpl)ServiceManager.getService(project, VcsUserRegistry.class);
|
||||
myFatalErrorsConsumer = fatalErrorsConsumer;
|
||||
|
||||
myHashMap = createLogHashMap();
|
||||
VcsLogProgress progress = new VcsLogProgress();
|
||||
Disposer.register(this, progress);
|
||||
|
||||
VcsLogCachesInvalidator invalidator = CachesInvalidator.EP_NAME.findExtension(VcsLogCachesInvalidator.class);
|
||||
if (invalidator.isValid()) {
|
||||
myHashMap = createLogHashMap();
|
||||
myIndex = new VcsLogPersistentIndex(myProject, myHashMap, progress, logProviders, myFatalErrorsConsumer, this);
|
||||
}
|
||||
else {
|
||||
// this is not recoverable
|
||||
// restart won't help here
|
||||
// and can not shut down ide because of this
|
||||
// so use memory storage (probably leading to out of memory at some point) + no index
|
||||
String message = "Could not delete " + PersistentUtil.LOG_CACHE + "\nDelete it manually and restart IDEA.";
|
||||
LOG.error(message);
|
||||
myFatalErrorsConsumer.displayFatalErrorMessage(message);
|
||||
myHashMap = new InMemoryStorage();
|
||||
myIndex = new EmptyIndex();
|
||||
}
|
||||
|
||||
myTopCommitsDetailsCache = new TopCommitsCache(myHashMap);
|
||||
myMiniDetailsGetter = new MiniDetailsGetter(myHashMap, logProviders, myTopCommitsDetailsCache, this);
|
||||
myDetailsGetter = new CommitDetailsGetter(myHashMap, logProviders, this);
|
||||
|
||||
VcsLogProgress progress = new VcsLogProgress();
|
||||
Disposer.register(this, progress);
|
||||
myIndex = new VcsLogPersistentIndex(myProject, myHashMap, progress, logProviders, myFatalErrorsConsumer, this);
|
||||
|
||||
myRefresher = new VcsLogRefresherImpl(myProject, myHashMap, myLogProviders, myUserRegistry, myIndex, progress, myTopCommitsDetailsCache,
|
||||
this::fireDataPackChangeEvent, FAILING_EXCEPTION_HANDLER, RECENT_COMMITS_COUNT);
|
||||
|
||||
|
||||
@@ -20,4 +20,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface FatalErrorConsumer {
|
||||
void consume(@Nullable Object source, @NotNull Exception exception);
|
||||
|
||||
void displayFatalErrorMessage(@NotNull String message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 com.intellij.vcs.log.impl;
|
||||
|
||||
import com.intellij.ide.caches.CachesInvalidator;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.vcs.log.util.PersistentUtil;
|
||||
|
||||
public class VcsLogCachesInvalidator extends CachesInvalidator {
|
||||
|
||||
public synchronized boolean isValid() {
|
||||
if (PersistentUtil.getCorruptionMarkerFile().exists()) {
|
||||
boolean deleted = FileUtil.delete(PersistentUtil.LOG_CACHE);
|
||||
if (!deleted) {
|
||||
// if could not delete caches, ensure that corruption marker is still there
|
||||
FileUtil.createIfDoesntExist(PersistentUtil.getCorruptionMarkerFile());
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaches() {
|
||||
if (PersistentUtil.LOG_CACHE.exists()) {
|
||||
String[] children = PersistentUtil.LOG_CACHE.list();
|
||||
if (!ArrayUtil.isEmpty(children)) {
|
||||
FileUtil.createIfDoesntExist(PersistentUtil.getCorruptionMarkerFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,5 +240,10 @@ public class VcsLogManager implements Disposable {
|
||||
myLogData.getIndex().markCorrupted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayFatalErrorMessage(@NotNull String message) {
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myProject, message, MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.vcs.log.impl;
|
||||
|
||||
import com.intellij.ide.caches.CachesInvalidator;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -111,7 +112,10 @@ public class VcsProjectLog {
|
||||
logManager.scheduleInitialization();
|
||||
}
|
||||
else if (PostponableLogRefresher.keepUpToDate()) {
|
||||
HeavyAwareExecutor.executeOutOfHeavyProcessLater(logManager::scheduleInitialization, 5000);
|
||||
VcsLogCachesInvalidator invalidator = CachesInvalidator.EP_NAME.findExtension(VcsLogCachesInvalidator.class);
|
||||
if (invalidator.isValid()) {
|
||||
HeavyAwareExecutor.executeOutOfHeavyProcessLater(logManager::scheduleInitialization, 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.Map;
|
||||
|
||||
public class PersistentUtil {
|
||||
@NotNull public static final File LOG_CACHE = new File(PathManager.getSystemPath(), "vcs-log");
|
||||
@NotNull private static final String CORRUPTION_MARKER = "corruption.marker";
|
||||
|
||||
@NotNull
|
||||
public static String calcLogId(@NotNull Project project, @NotNull Map<VirtualFile, VcsLogProvider> logProviders) {
|
||||
@@ -83,4 +84,9 @@ public class PersistentUtil {
|
||||
new PersistentHashMap<>(storageFile, new IntInlineKeyDescriptor(), externalizer, Page.PAGE_SIZE),
|
||||
storageFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File getCorruptionMarkerFile() {
|
||||
return new File(LOG_CACHE, CORRUPTION_MARKER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.vcs.log.graph.GraphCommit;
|
||||
import com.intellij.vcs.log.impl.*;
|
||||
import com.intellij.vcs.test.VcsPlatformTest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
@@ -194,7 +195,17 @@ public class VcsLogRefresherTest extends VcsPlatformTest {
|
||||
}
|
||||
|
||||
private VcsLogRefresherImpl createLoader(Consumer<DataPack> dataPackConsumer) {
|
||||
myLogData = new VcsLogData(myProject, myLogProviders, (source, exception) -> LOG.error(exception));
|
||||
myLogData = new VcsLogData(myProject, myLogProviders, new FatalErrorHandler() {
|
||||
@Override
|
||||
public void consume(@Nullable Object source, @NotNull Exception exception) {
|
||||
LOG.error(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayFatalErrorMessage(@NotNull String message) {
|
||||
LOG.error(message);
|
||||
}
|
||||
});
|
||||
Disposer.register(myProject, myLogData);
|
||||
return new VcsLogRefresherImpl(myProject, myLogData.getHashMap(), myLogProviders, myLogData.getUserRegistry(), myLogData.getIndex(),
|
||||
new VcsLogProgress(),
|
||||
|
||||
@@ -247,31 +247,5 @@ class VisiblePackBuilderTest {
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyIndex : VcsLogIndex {
|
||||
override fun isIndexed(root: VirtualFile): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isIndexed(commit: Int): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canFilter(filters: MutableList<VcsLogDetailsFilter>): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun scheduleIndex(full: Boolean) {
|
||||
}
|
||||
|
||||
override fun markForIndexing(index: Int, root: VirtualFile) {
|
||||
}
|
||||
|
||||
override fun filter(detailsFilters: MutableList<VcsLogDetailsFilter>): MutableSet<Int> {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun markCorrupted() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user