diff --git a/package.json b/package.json index 3bd68dc..e6e3434 100644 --- a/package.json +++ b/package.json @@ -6960,6 +6960,11 @@ "icon": "$(window)" }, { + "command": "gitlens.views.workspaces.changeLocalSync", + "title": "Change Workspace Sync Setting...", + "category": "GitLens" + }, + { "command": "gitlens.views.workspaces.repo.locate", "title": "Locate Repository...", "category": "GitLens", @@ -9518,6 +9523,10 @@ "when": "false" }, { + "command": "gitlens.views.workspaces.changeLocalSync", + "when": "false" + }, + { "command": "gitlens.views.workspaces.repo.openInNewWindow", "when": "false" }, @@ -11182,6 +11191,11 @@ "group": "2_gitlens_quickopen@5" }, { + "command": "gitlens.views.workspaces.changeLocalSync", + "when": "viewItem =~ /(gitlens:workspace\\b(?=.*?\\b\\+(cloud|local)\\b)(?=.*?\\b\\+current\\b)(?=.*?\\b\\+hasPath\\b)|gitlens:repositories\\b(?=.*?\\b\\+synced\\b))/", + "group": "2_gitlens_quickopen@6" + }, + { "command": "gitlens.views.workspaces.delete", "when": "viewItem =~ /gitlens:workspace\\b(?=.*?\\b\\+cloud\\b)/", "group": "6_gitlens_actions@1" diff --git a/src/constants.ts b/src/constants.ts index c376bbe..aed6bd5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -404,6 +404,7 @@ export type TreeViewCommands = `gitlens.views.${ | 'copy' | 'refresh' | 'addRepos' + | 'changeLocalSync' | 'convert' | 'create' | 'createLocal' diff --git a/src/env/browser/pathMapping/workspacesWebPathMappingProvider.ts b/src/env/browser/pathMapping/workspacesWebPathMappingProvider.ts index 9230734..ac1ae31 100644 --- a/src/env/browser/pathMapping/workspacesWebPathMappingProvider.ts +++ b/src/env/browser/pathMapping/workspacesWebPathMappingProvider.ts @@ -39,4 +39,11 @@ export class WorkspacesWebPathMappingProvider implements WorkspacesPathMappingPr ): Promise { return false; } + + async updateCodeWorkspaceFileSettings( + _uri: Uri, + _options: { workspaceSyncSetting?: WorkspaceSyncSetting }, + ): Promise { + return false; + } } diff --git a/src/env/node/pathMapping/workspacesLocalPathMappingProvider.ts b/src/env/node/pathMapping/workspacesLocalPathMappingProvider.ts index cf3a28b..cb7aa9b 100644 --- a/src/env/node/pathMapping/workspacesLocalPathMappingProvider.ts +++ b/src/env/node/pathMapping/workspacesLocalPathMappingProvider.ts @@ -211,4 +211,32 @@ export class WorkspacesLocalPathMappingProvider implements WorkspacesPathMapping return true; } + + async updateCodeWorkspaceFileSettings( + uri: Uri, + options: { workspaceSyncSetting?: WorkspaceSyncSetting }, + ): Promise { + let codeWorkspaceFileContents: CodeWorkspaceFileContents; + let data; + try { + data = await workspace.fs.readFile(uri); + codeWorkspaceFileContents = JSON.parse(data.toString()) as CodeWorkspaceFileContents; + } catch (error) { + return false; + } + + if (options.workspaceSyncSetting != null) { + codeWorkspaceFileContents.settings['gitkraken.workspaceSyncSetting'] = options.workspaceSyncSetting; + } + + const outputData = new Uint8Array(Buffer.from(JSON.stringify(codeWorkspaceFileContents))); + try { + await workspace.fs.writeFile(uri, outputData); + } catch (error) { + Logger.error(error, 'updateCodeWorkspaceFileSettings'); + return false; + } + + return true; + } } diff --git a/src/plus/workspaces/workspacesPathMappingProvider.ts b/src/plus/workspaces/workspacesPathMappingProvider.ts index 522d483..b61c6b6 100644 --- a/src/plus/workspaces/workspacesPathMappingProvider.ts +++ b/src/plus/workspaces/workspacesPathMappingProvider.ts @@ -28,4 +28,9 @@ export interface WorkspacesPathMappingProvider { workspaceRepoFilePaths: string[], options?: { workspaceId?: string; workspaceSyncSetting?: WorkspaceSyncSetting }, ): Promise; + + updateCodeWorkspaceFileSettings( + uri: Uri, + options: { workspaceSyncSetting?: WorkspaceSyncSetting }, + ): Promise; } diff --git a/src/plus/workspaces/workspacesService.ts b/src/plus/workspaces/workspacesService.ts index 8bba807..65ebeec 100644 --- a/src/plus/workspaces/workspacesService.ts +++ b/src/plus/workspaces/workspacesService.ts @@ -68,6 +68,10 @@ export class WorkspacesService implements Disposable { this._disposable.dispose(); } + get currentWorkspaceId(): string | undefined { + return this._currentWorkspaceId; + } + private onSubscriptionChanged(event: SubscriptionChangeEvent): void { if ( event.current.account == null || @@ -1030,6 +1034,41 @@ export class WorkspacesService implements Disposable { void this.openCodeWorkspaceFile(workspaceId, { location: open.location }); } + async changeCurrentCodeWorkspaceSyncSetting(): Promise { + if ( + workspace.workspaceFile == null || + this._currentWorkspaceId == null || + this._currentWorkspaceSyncSetting == null + ) { + return; + } + + let syncOptions = [ + { title: 'Always', option: WorkspaceSyncSetting.Always }, + { title: 'Never', option: WorkspaceSyncSetting.Never }, + { title: 'Ask every time', option: WorkspaceSyncSetting.Ask }, + ]; + syncOptions = syncOptions.filter(s => s.option !== this._currentWorkspaceSyncSetting); + + // Show a quickpick without the current sync setting as an option + const newWorkspaceSyncOption = await window.showQuickPick( + syncOptions.map(s => s.title), + { + placeHolder: 'Choose a new sync setting for this workspace', + }, + ); + if (newWorkspaceSyncOption == null) return; + + const newWorkspaceSyncSetting = syncOptions.find(s => s.title === newWorkspaceSyncOption)?.option; + if (newWorkspaceSyncSetting == null) return; + + const updated = await this._workspacesPathProvider.updateCodeWorkspaceFileSettings(workspace.workspaceFile, { + workspaceSyncSetting: newWorkspaceSyncSetting, + }); + if (!updated) return; + this._currentWorkspaceSyncSetting = newWorkspaceSyncSetting; + } + async openCodeWorkspaceFile(workspaceId: string, options?: { location?: OpenWorkspaceLocation }): Promise { const workspace = this.getCloudWorkspace(workspaceId) ?? this.getLocalWorkspace(workspaceId); if (workspace == null) return; diff --git a/src/views/nodes/repositoriesNode.ts b/src/views/nodes/repositoriesNode.ts index 9746bfc..e4bd806 100644 --- a/src/views/nodes/repositoriesNode.ts +++ b/src/views/nodes/repositoriesNode.ts @@ -51,6 +51,7 @@ export class RepositoriesNode extends SubscribeableViewNode { + await this.container.workspaces.changeCurrentCodeWorkspaceSyncSetting(); + }, + this, + ), + registerViewCommand( this.getQualifiedCommand('delete'), async (node: WorkspaceNode) => { await this.container.workspaces.deleteCloudWorkspace(node.workspace.id);