Skip to content

Commit

Permalink
[Insiders] Throwing error when a file is edited and saved from a diff…
Browse files Browse the repository at this point in the history
… view (fix #123756)
  • Loading branch information
bpasero committed May 13, 2021
1 parent 659175f commit 23dc403
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/vs/platform/files/common/fileService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export class FileService extends Disposable implements IFileService {
mtime: stat.mtime,
ctime: stat.ctime,
size: stat.size,
readonly: Boolean(stat.permissions ?? 0 & FilePermission.Readonly) ?? Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
readonly: Boolean(stat.permissions ?? 0 & FilePermission.Readonly) || Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
etag: etag({ mtime: stat.mtime, size: stat.size })
};

Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/contrib/files/common/explorerModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class ExplorerModel implements IDisposable {
fileService: IFileService
) {
const setRoots = () => this._roots = this.contextService.getWorkspace().folders
.map(folder => new ExplorerItem(folder.uri, fileService, undefined, true, false, folder.name));
.map(folder => new ExplorerItem(folder.uri, fileService, undefined, true, false, false, folder.name));
setRoots();

this._listener = this.contextService.onDidChangeWorkspaceFolders(() => {
Expand Down Expand Up @@ -89,6 +89,7 @@ export class ExplorerItem {
private _parent: ExplorerItem | undefined,
private _isDirectory?: boolean,
private _isSymbolicLink?: boolean,
private _readonly?: boolean,
private _name: string = basenameOrAuthority(resource),
private _mtime?: number,
private _unknown = false
Expand Down Expand Up @@ -124,7 +125,7 @@ export class ExplorerItem {
}

get isReadonly(): boolean {
return this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
return this._readonly || this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
}

get mtime(): number | undefined {
Expand Down Expand Up @@ -179,7 +180,7 @@ export class ExplorerItem {
}

static create(fileService: IFileService, raw: IFileStat, parent: ExplorerItem | undefined, resolveTo?: readonly URI[]): ExplorerItem {
const stat = new ExplorerItem(raw.resource, fileService, parent, raw.isDirectory, raw.isSymbolicLink, raw.name, raw.mtime, !raw.isFile && !raw.isDirectory);
const stat = new ExplorerItem(raw.resource, fileService, parent, raw.isDirectory, raw.isSymbolicLink, raw.readonly, raw.name, raw.mtime, !raw.isFile && !raw.isDirectory);

// Recursively add children if present
if (stat.isDirectory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { TestFileService } from 'vs/workbench/test/browser/workbenchTestServices

const fileService = new TestFileService();
function createStat(this: any, path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number): ExplorerItem {
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, false, name, mtime);
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, false, false, name, mtime);
}

suite('Files - View Model', function () {
Expand Down Expand Up @@ -245,19 +245,19 @@ suite('Files - View Model', function () {
});

test('Merge Local with Disk', function () {
const merge1 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, 'to', Date.now());
const merge2 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, 'to', Date.now());
const merge1 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, false, 'to', Date.now());
const merge2 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, false, 'to', Date.now());

// Merge Properties
ExplorerItem.mergeLocalWithDisk(merge2, merge1);
assert.strictEqual(merge1.mtime, merge2.mtime);

// Merge Child when isDirectoryResolved=false is a no-op
merge2.addChild(new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, 'foo.html', Date.now()));
merge2.addChild(new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, false, 'foo.html', Date.now()));
ExplorerItem.mergeLocalWithDisk(merge2, merge1);

// Merge Child with isDirectoryResolved=true
const child = new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, 'foo.html', Date.now());
const child = new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, false, 'foo.html', Date.now());
merge2.removeChild(child);
merge2.addChild(child);
(<any>merge2)._isDirectoryResolved = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const $ = dom.$;
const fileService = new TestFileService();

function createStat(this: any, path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number, isSymLink = false, isUnknown = false): ExplorerItem {
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, isSymLink, name, mtime, isUnknown);
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, isSymLink, false, name, mtime, isUnknown);
}

suite('Files - ExplorerView', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE
}

isReadonly(): boolean {
return this._fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
return this._workingCopy?.isReadonly() || this._fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
}

revert(options?: IRevertOptions): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}

override isReadonly(): boolean {
return this.lastResolvedFileStat?.readonly ?? this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
return this.lastResolvedFileStat?.readonly || this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
}

override dispose(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ export interface IFileWorkingCopy<T extends IFileWorkingCopyModel> extends IReso
* Whether we have a resolved model or not.
*/
isResolved(): this is IResolvedFileWorkingCopy<T>;

/**
* Whether the file working copy is readonly or not.
*/
isReadonly(): boolean;
}

export interface IResolvedFileWorkingCopy<T extends IFileWorkingCopyModel> extends IFileWorkingCopy<T> {
Expand Down Expand Up @@ -1235,7 +1240,7 @@ export class FileWorkingCopy<T extends IFileWorkingCopyModel> extends ResourceWo
}

isReadonly(): boolean {
return this.lastResolvedFileStat?.readonly ?? this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
return this.lastResolvedFileStat?.readonly || this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
}

private trace(msg: string): void {
Expand Down

0 comments on commit 23dc403

Please sign in to comment.