fix: do not enqueue write operations on conflict

Closes #2051

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2023-05-09 12:06:56 +02:00 committed by Akos Kitta
parent 278dd4ba87
commit 117b2a4fc7

View File

@ -1,3 +1,4 @@
import { ResourceSaveOptions } from '@theia/core/lib/common/resource';
import URI from '@theia/core/lib/common/uri'; import URI from '@theia/core/lib/common/uri';
import { injectable } from '@theia/core/shared/inversify'; import { injectable } from '@theia/core/shared/inversify';
import { import {
@ -7,6 +8,7 @@ import {
} from '@theia/filesystem/lib/browser/file-resource'; } from '@theia/filesystem/lib/browser/file-resource';
import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { FileService } from '@theia/filesystem/lib/browser/file-service';
import { import {
ETAG_DISABLED,
FileOperationError, FileOperationError,
FileOperationResult, FileOperationResult,
} from '@theia/filesystem/lib/common/files'; } from '@theia/filesystem/lib/common/files';
@ -51,8 +53,16 @@ class WriteQueuedFileResource extends FileResource {
) { ) {
super(uri, fileService, options); super(uri, fileService, options);
const originalDoWrite = this['doWrite']; const originalDoWrite = this['doWrite'];
this['doWrite'] = (content, options) => this['doWrite'] = (content, options) => {
this.writeQueue.add(() => originalDoWrite.bind(this)(content, options)); if (isETagDisabledResourceSaveOptions(options)) {
// When force overriding without auto-save do not enqueue the modification, it's already enqueued and the conflict is just being resolved.
// https://github.com/arduino/arduino-ide/issues/2051
return originalDoWrite.bind(this)(content, options);
}
return this.writeQueue.add(() =>
originalDoWrite.bind(this)(content, options)
);
};
const originalSaveStream = this['saveStream']; const originalSaveStream = this['saveStream'];
if (originalSaveStream) { if (originalSaveStream) {
this['saveStream'] = (content, options) => this['saveStream'] = (content, options) =>
@ -83,3 +93,24 @@ class WriteQueuedFileResource extends FileResource {
return super.isInSync(); return super.isInSync();
} }
} }
// Theia incorrectly sets the disabled ETag on the `stat` instead of the `version` so `FileResourceVersion#is` is unusable.
// https://github.com/eclipse-theia/theia/blob/f9063625b861b8433341fcd1a29a0d0298778f4c/packages/filesystem/src/browser/file-resource.ts#L210
// https://github.com/eclipse-theia/theia/blob/f9063625b861b8433341fcd1a29a0d0298778f4c/packages/filesystem/src/browser/file-resource.ts#L34
// https://github.com/eclipse-theia/theia/discussions/12502
function isETagDisabledResourceSaveOptions(
options?: ResourceSaveOptions
): boolean {
if (typeof options === 'object') {
if ('version' in options && typeof options['version'] === 'object') {
const version = <Record<string, unknown>>options['version'];
if (version && 'stat' in version && typeof version['stat'] === 'object') {
const stat = <Record<string, unknown>>version['stat'];
if (stat) {
return 'etag' in stat && stat['etag'] === ETAG_DISABLED;
}
}
}
}
return false;
}