[log] IJPL-178589 Execute markCorrupted outside iterateChangesInCommits

(cherry picked from commit 8063179464b8eb66696b397e05b336500c9e3aa6)

IJ-MR-161542

GitOrigin-RevId: 21db1ce2ee2d6ea064ed5485be7397820e5e8a76
This commit is contained in:
Ilia.Shulgin
2025-04-25 17:22:26 +02:00
committed by intellij-monorepo-bot
parent 70c7faa060
commit e44cfceff5

View File

@@ -260,33 +260,39 @@ public final class IndexDataGetter {
VirtualFile root = getRoot(path);
if (myProviders.containsKey(root) && root != null) {
executeAndCatch(() -> {
myIndexStorageBackend.iterateChangesInCommits(root, path, (changes, commit) -> executeAndCatch(() -> {
int[] parents = myIndexStorageBackend.getParents(commit);
if (parents == null) {
throw new CorruptedDataException("No parents for commit " + commit);
}
List<Exception> corruptedDataExceptions = new ArrayList<>();
try {
executeAndCatch(() -> {
myIndexStorageBackend.iterateChangesInCommits(root, path, (changes, commit) -> {
collectCorruptedDataExceptions(corruptedDataExceptions, () -> {
int[] parents = myIndexStorageBackend.getParents(commit);
if (parents == null) {
throw new CorruptedDataException("No parents for commit " + commit);
}
Int2ObjectMap<ChangeKind> changeMap = new Int2ObjectOpenHashMap<>(parents.length);
if (parents.length == 0 && !changes.isEmpty()) {
changeMap.put(commit, ContainerUtil.getFirstItem(changes));
}
else {
if (parents.length != changes.size()) {
throw new CorruptedDataException("Commit " + commit + " has " + parents.length +
" parents, but " + changes.size() + " changes.");
}
for (int i = 0, length = parents.length; i < length; i++) {
changeMap.put(parents[i], changes.get(i));
}
}
Int2ObjectMap<ChangeKind> changeMap = new Int2ObjectOpenHashMap<>(parents.length);
if (parents.length == 0 && !changes.isEmpty()) {
changeMap.put(commit, ContainerUtil.getFirstItem(changes));
}
else {
if (parents.length != changes.size()) {
throw new CorruptedDataException("Commit " + commit + " has " + parents.length +
" parents, but " + changes.size() + " changes.");
}
for (int i = 0, length = parents.length; i < length; i++) {
changeMap.put(parents[i], changes.get(i));
}
}
affectedCommits.put(commit, changeMap);
return null;
}));
return null;
});
affectedCommits.put(commit, changeMap);
});
});
});
} finally {
if (!corruptedDataExceptions.isEmpty()) {
handleCorruptedData(corruptedDataExceptions);
}
}
}
return affectedCommits;
}
@@ -428,27 +434,27 @@ public final class IndexDataGetter {
try {
return computable.compute();
}
catch (IOException | UncheckedIOException | StorageException | CorruptedDataException e) {
myErrorHandler.handleError(VcsLogErrorHandler.Source.Index, e);
myIndexStorageBackend.markCorrupted();
}
catch (RuntimeException e) {
processRuntimeException(e);
catch (Exception e) {
if (e instanceof ProcessCanceledException pce) {
throw pce;
}
else if (isCorruptedDataException(e)) {
handleCorruptedData(Collections.singletonList(e));
}
else {
LOG.error("Unknown exception in Vcs Log index processing", e);
throw new RuntimeException(e);
}
}
return defaultValue;
}
private void processRuntimeException(@NotNull RuntimeException e) {
if (e instanceof ProcessCanceledException) throw e;
if (e.getCause() instanceof IOException || e.getCause() instanceof StorageException) {
private void handleCorruptedData(List<Exception> exceptions) {
for (Exception e : exceptions) {
myErrorHandler.handleError(VcsLogErrorHandler.Source.Index, e);
myIndexStorageBackend.markCorrupted();
}
else {
LOG.error("Unknown exception in Vcs Log index processing", e);
throw new RuntimeException(e);
}
myIndexStorageBackend.markCorrupted();
}
private static final class CorruptedDataException extends RuntimeException {
@@ -457,6 +463,33 @@ public final class IndexDataGetter {
}
}
private static boolean isCorruptedDataException(@NotNull Exception e) {
if (e instanceof IOException ||
e instanceof UncheckedIOException ||
e instanceof StorageException ||
e instanceof CorruptedDataException) {
return true;
}
if (e instanceof RuntimeException) {
return e.getCause() instanceof IOException || e.getCause() instanceof StorageException;
}
return false;
}
private static void collectCorruptedDataExceptions(List<Exception> corruptedDataExceptions, Runnable runnable) {
try {
runnable.run();
} catch (Exception e) {
if (isCorruptedDataException(e)) {
corruptedDataExceptions.add(e);
} else {
throw e;
}
}
}
@FunctionalInterface
private interface Throwable2Runnable<E1 extends Throwable, E2 extends Throwable> {
void run() throws E1, E2;