Skip to content

Commit 54a0e43

Browse files
Set file readonly if class is deployed or if server-side source control reports it not editable (#1399)
* Mark as readonly deployed classes and source-control-protected ISFS documents * Add `objectscript.serverSourceControl.respectEditableStatus` setting * Improve description of `respectEditableStatus` Co-authored-by: Brett Saviano <[email protected]> * Apply feedback * Be consistently explicit about `false` defaults on boolean config properties * Revert addition of boolean property defaults in `objectscript.export` --------- Co-authored-by: Brett Saviano <[email protected]>
1 parent c426c7a commit 54a0e43

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed

package.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,14 @@
13251325
"objectscript.serverSourceControl.disableOtherActionTriggers": {
13261326
"description": "Prevent server-side source control 'other action' triggers from firing.",
13271327
"type": "boolean",
1328-
"scope": "resource"
1328+
"scope": "resource",
1329+
"default": false
1330+
},
1331+
"objectscript.serverSourceControl.respectEditableStatus": {
1332+
"markdownDescription": "Set `isfs` document readonly if GetStatus method of server-side source control class returns Editable = 0.",
1333+
"type": "boolean",
1334+
"scope": "resource",
1335+
"default": false
13291336
},
13301337
"objectscript.export": {
13311338
"type": "object",
@@ -1703,7 +1710,8 @@
17031710
},
17041711
"stopOnEntry": {
17051712
"type": "boolean",
1706-
"description": "Automatically stop target after attach. If not specified, target does not stop."
1713+
"description": "Automatically stop target after attach. If not specified, target does not stop.",
1714+
"default": false
17071715
}
17081716
}
17091717
}

src/providers/FileSystemProvider/File.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export class File implements vscode.FileStat {
55
public ctime: number;
66
public mtime: number;
77
public size: number;
8+
public permissions?: vscode.FilePermission;
89
public fileName: string;
910
public name: string;
1011
public data?: Uint8Array;

src/providers/FileSystemProvider/FileSystemProvider.ts

+53-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ import {
1313
redirectDotvscodeRoot,
1414
workspaceFolderOfUri,
1515
} from "../../utils/index";
16-
import { config, FILESYSTEM_SCHEMA, intLangId, macLangId, workspaceState } from "../../extension";
16+
import {
17+
config,
18+
FILESYSTEM_READONLY_SCHEMA,
19+
FILESYSTEM_SCHEMA,
20+
intLangId,
21+
macLangId,
22+
workspaceState,
23+
} from "../../extension";
1724
import { addIsfsFileToProject, modifyProject } from "../../commands/project";
1825
import { DocumentContentProvider } from "../DocumentContentProvider";
1926
import { Document, UserAction } from "../../api/atelier";
@@ -184,13 +191,55 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
184191
this._fireSoon({ type: vscode.FileChangeType.Changed, uri });
185192
}
186193

187-
public stat(uri: vscode.Uri): Promise<vscode.FileStat> {
194+
public async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
195+
let entryPromise: Promise<Entry>;
196+
let result: Entry;
188197
const redirectedUri = redirectDotvscodeRoot(uri);
189198
if (redirectedUri.path !== uri.path) {
190199
// When redirecting the /.vscode subtree we must fill in as-yet-unvisited folders to fix https://github.com/intersystems-community/vscode-objectscript/issues/1143
191-
return this._lookup(redirectedUri, true);
200+
entryPromise = this._lookup(redirectedUri, true);
201+
} else {
202+
entryPromise = this._lookup(uri);
203+
}
204+
205+
// If this is our readonly variant there's no point checking server-side whether the file sould be marked readonly
206+
if (uri.scheme === FILESYSTEM_READONLY_SCHEMA) {
207+
return entryPromise;
208+
}
209+
210+
if (entryPromise instanceof File) {
211+
// previously resolved as a file
212+
result = entryPromise;
213+
} else if (entryPromise instanceof Promise && uri.path.split("/").pop()?.split(".").length > 1) {
214+
// apparently a file, so resolve ahead of adding permissions
215+
result = await entryPromise;
216+
} else {
217+
// otherwise return the promise
218+
return entryPromise;
219+
}
220+
221+
//
222+
if (result instanceof File) {
223+
const api = new AtelierAPI(uri);
224+
const serverName = isCSPFile(uri) ? uri.path : uri.path.slice(1).replace(/\//g, ".");
225+
if (serverName.slice(-4).toLowerCase() == ".cls") {
226+
if (await isClassDeployed(serverName, api)) {
227+
result.permissions |= vscode.FilePermission.Readonly;
228+
return result;
229+
}
230+
}
231+
232+
// Does server-side source control report it as editable?
233+
if (vscode.workspace.getConfiguration("objectscript.serverSourceControl", uri)?.get("respectEditableStatus")) {
234+
const query = "select * from %Atelier_v1_Utils.Extension_GetStatus(?)";
235+
const statusObj = await api.actionQuery(query, [serverName]);
236+
const docStatus = statusObj.result?.content?.pop();
237+
if (docStatus) {
238+
result.permissions = docStatus.editable ? undefined : result.permissions | vscode.FilePermission.Readonly;
239+
}
240+
}
192241
}
193-
return this._lookup(uri);
242+
return result;
194243
}
195244

196245
public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {

0 commit comments

Comments
 (0)