|  | 
|  | 1 | +import { ResourceSaveOptions } from '@theia/core/lib/common/resource'; | 
| 1 | 2 | import URI from '@theia/core/lib/common/uri'; | 
| 2 | 3 | import { injectable } from '@theia/core/shared/inversify'; | 
| 3 | 4 | import { | 
|  | 
| 7 | 8 | } from '@theia/filesystem/lib/browser/file-resource'; | 
| 8 | 9 | import { FileService } from '@theia/filesystem/lib/browser/file-service'; | 
| 9 | 10 | import { | 
|  | 11 | +  ETAG_DISABLED, | 
| 10 | 12 |   FileOperationError, | 
| 11 | 13 |   FileOperationResult, | 
| 12 | 14 | } from '@theia/filesystem/lib/common/files'; | 
| @@ -51,8 +53,16 @@ class WriteQueuedFileResource extends FileResource { | 
| 51 | 53 |   ) { | 
| 52 | 54 |     super(uri, fileService, options); | 
| 53 | 55 |     const originalDoWrite = this['doWrite']; | 
| 54 |  | -    this['doWrite'] = (content, options) => | 
| 55 |  | -      this.writeQueue.add(() => originalDoWrite.bind(this)(content, options)); | 
|  | 56 | +    this['doWrite'] = (content, options) => { | 
|  | 57 | +      if (isETagDisabledResourceSaveOptions(options)) { | 
|  | 58 | +        // When force overriding without auto-save do not enqueue the modification, it's already enqueued and the conflict is just being resolved. | 
|  | 59 | +        // https://github.com/arduino/arduino-ide/issues/2051 | 
|  | 60 | +        return originalDoWrite.bind(this)(content, options); | 
|  | 61 | +      } | 
|  | 62 | +      return this.writeQueue.add(() => | 
|  | 63 | +        originalDoWrite.bind(this)(content, options) | 
|  | 64 | +      ); | 
|  | 65 | +    }; | 
| 56 | 66 |     const originalSaveStream = this['saveStream']; | 
| 57 | 67 |     if (originalSaveStream) { | 
| 58 | 68 |       this['saveStream'] = (content, options) => | 
| @@ -83,3 +93,24 @@ class WriteQueuedFileResource extends FileResource { | 
| 83 | 93 |     return super.isInSync(); | 
| 84 | 94 |   } | 
| 85 | 95 | } | 
|  | 96 | + | 
|  | 97 | +// Theia incorrectly sets the disabled ETag on the `stat` instead of the `version` so `FileResourceVersion#is` is unusable. | 
|  | 98 | +// https://github.com/eclipse-theia/theia/blob/f9063625b861b8433341fcd1a29a0d0298778f4c/packages/filesystem/src/browser/file-resource.ts#L210 | 
|  | 99 | +// https://github.com/eclipse-theia/theia/blob/f9063625b861b8433341fcd1a29a0d0298778f4c/packages/filesystem/src/browser/file-resource.ts#L34 | 
|  | 100 | +// https://github.com/eclipse-theia/theia/discussions/12502 | 
|  | 101 | +function isETagDisabledResourceSaveOptions( | 
|  | 102 | +  options?: ResourceSaveOptions | 
|  | 103 | +): boolean { | 
|  | 104 | +  if (typeof options === 'object') { | 
|  | 105 | +    if ('version' in options && typeof options['version'] === 'object') { | 
|  | 106 | +      const version = <Record<string, unknown>>options['version']; | 
|  | 107 | +      if (version && 'stat' in version && typeof version['stat'] === 'object') { | 
|  | 108 | +        const stat = <Record<string, unknown>>version['stat']; | 
|  | 109 | +        if (stat) { | 
|  | 110 | +          return 'etag' in stat && stat['etag'] === ETAG_DISABLED; | 
|  | 111 | +        } | 
|  | 112 | +      } | 
|  | 113 | +    } | 
|  | 114 | +  } | 
|  | 115 | +  return false; | 
|  | 116 | +} | 
0 commit comments