Skip to content

Commit 6a49a22

Browse files
Improves handling of 'delete worktree' action on merge target when the default worktree is already open (#4245)
* Fixes `getCommonRepository` failing when the path is a git dir * Moves pending deep link to secret storage * Listens for an processes pending deep links when relevant to window * Closes current window if needed after delete worktree handoff
1 parent 1e4993f commit 6a49a22

File tree

5 files changed

+78
-26
lines changed

5 files changed

+78
-26
lines changed

src/constants.commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export type CoreCommands =
147147
| 'workbench.action.closeActiveEditor'
148148
| 'workbench.action.closeAllEditors'
149149
| 'workbench.action.closePanel'
150+
| 'workbench.action.closeWindow'
150151
| 'workbench.action.focusRightGroup'
151152
| 'workbench.action.nextEditor'
152153
| 'workbench.action.newGroupRight'

src/constants.storage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import type { DeepLinkServiceState } from './uris/deepLinks/deepLink';
1414
export type SecretKeys =
1515
| IntegrationAuthenticationKeys
1616
| `gitlens.${AIProviders}.key`
17-
| `gitlens.plus.auth:${Environment}`;
17+
| `gitlens.plus.auth:${Environment}`
18+
| 'deepLinks:pending';
1819

1920
export type IntegrationAuthenticationKeys =
2021
| `gitlens.integration.auth:${IntegrationId}|${string}`
@@ -64,7 +65,6 @@ export type GlobalStorage = {
6465
avatars: [string, StoredAvatar][];
6566
'confirm:ai:tos': boolean;
6667
repoVisibility: [string, StoredRepoVisibilityInfo][];
67-
'deepLinks:pending': StoredDeepLinkContext;
6868
pendingWhatsNewOnFocus: boolean;
6969
// Don't change this key name ('premium`) as its the stored subscription
7070
'premium:subscription': Stored<Subscription & { lastValidatedAt: number | undefined }>;

src/git/models/repository.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,11 @@ export class Repository implements Disposable {
625625
@gate()
626626
@log({ exit: true })
627627
async getCommonRepository(): Promise<Repository | undefined> {
628-
const gitDir = await this.git.config().getGitDir?.();
629-
if (gitDir?.commonUri == null) return this;
628+
const uri = await this.getCommonRepositoryUri();
629+
if (uri == null) return this;
630630

631631
// If the repository isn't already opened, then open it as a "closed" repo (won't show up in the UI)
632-
return this.container.git.getOrOpenRepository(gitDir.commonUri, {
632+
return this.container.git.getOrOpenRepository(uri, {
633633
detectNested: false,
634634
force: true,
635635
closeOnOpen: true,

src/uris/deepLinks/deepLinkService.ts

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { QuickPickItem } from 'vscode';
1+
import type { QuickPickItem, SecretStorageChangeEvent } from 'vscode';
22
import { Disposable, env, EventEmitter, ProgressLocation, Range, Uri, window, workspace } from 'vscode';
33
import type { OpenCloudPatchCommandArgs } from '../../commands/patches';
44
import type { StoredDeepLinkContext, StoredNamedRef } from '../../constants.storage';
@@ -72,16 +72,43 @@ export class DeepLinkService implements Disposable {
7272
this._disposables.push(
7373
this._onDeepLinkProgressUpdated,
7474
container.uri.onDidReceiveUri(async (uri: Uri) => this.processDeepLinkUri(uri)),
75+
container.storage.onDidChangeSecrets(this.onDidChangeStorage, this),
7576
);
7677

77-
const pendingDeepLink = this.container.storage.get('deepLinks:pending');
78-
void this.processPendingDeepLink(pendingDeepLink);
78+
void this.container.storage.getSecret('deepLinks:pending').then(pendingDeepLink => {
79+
if (pendingDeepLink != null) {
80+
const link = JSON.parse(pendingDeepLink) as StoredDeepLinkContext;
81+
void this.processPendingDeepLink(link);
82+
}
83+
});
7984
}
8085

8186
dispose(): void {
8287
Disposable.from(...this._disposables).dispose();
8388
}
8489

90+
private async onDidChangeStorage(e: SecretStorageChangeEvent): Promise<void> {
91+
if (e.key === 'deepLinks:pending') {
92+
const pendingDeepLinkStored = await this.container.storage.getSecret('deepLinks:pending');
93+
if (pendingDeepLinkStored == null) return;
94+
95+
const pendingDeepLink = JSON.parse(pendingDeepLinkStored) as StoredDeepLinkContext;
96+
if (pendingDeepLink?.url == null) return;
97+
98+
const link = parseDeepLinkUri(Uri.parse(pendingDeepLink.url));
99+
if (link == null) return;
100+
101+
// TODO: See if we can remove this condition without breaking other link flows
102+
if (link.action !== DeepLinkActionType.DeleteBranch) return;
103+
104+
// see if there is a matching repo in the current window
105+
await this.findMatchingRepositoryFromCurrentWindow(link.repoPath, link.remoteUrl, link.mainId, true);
106+
if (this._context.repo != null) {
107+
void this.processPendingDeepLink(pendingDeepLink);
108+
}
109+
}
110+
}
111+
85112
private resetContext() {
86113
this._context = {
87114
state: DeepLinkServiceState.Idle,
@@ -203,14 +230,24 @@ export class DeepLinkService implements Disposable {
203230
repoPath: string | undefined,
204231
remoteUrl: string | undefined,
205232
repoId: string | undefined,
233+
openOnly: boolean = false,
206234
): Promise<void> {
207235
if (repoPath != null) {
208236
const repoOpenUri = maybeUri(repoPath) ? Uri.parse(repoPath) : repoPath;
209237
try {
210-
const openRepo = await this.container.git.getOrOpenRepository(repoOpenUri, { detectNested: false });
211-
if (openRepo != null) {
212-
this._context.repo = openRepo;
213-
return;
238+
if (openOnly) {
239+
for (const repo of this.container.git.openRepositories) {
240+
if (repo.path === repoPath || repo.uri.fsPath === repoPath) {
241+
this._context.repo = repo;
242+
return;
243+
}
244+
}
245+
} else {
246+
const openRepo = await this.container.git.getOrOpenRepository(repoOpenUri, { detectNested: false });
247+
if (openRepo != null) {
248+
this._context.repo = openRepo;
249+
return;
250+
}
214251
}
215252
} catch {}
216253
}
@@ -223,7 +260,7 @@ export class DeepLinkService implements Disposable {
223260

224261
// Try to match a repo using the remote URL first, since that saves us some steps.
225262
// As a fallback, try to match using the repo id.
226-
for (const repo of this.container.git.repositories) {
263+
for (const repo of openOnly ? this.container.git.openRepositories : this.container.git.repositories) {
227264
if (repoPath != null && normalizePath(repo.path.toLowerCase()) === normalizePath(repoPath.toLowerCase())) {
228265
this._context.repo = repo;
229266
return;
@@ -254,7 +291,7 @@ export class DeepLinkService implements Disposable {
254291
@debug()
255292
private async processPendingDeepLink(pendingDeepLink: StoredDeepLinkContext | undefined) {
256293
if (pendingDeepLink == null) return;
257-
void this.container.storage.delete('deepLinks:pending');
294+
void this.container.storage.deleteSecret('deepLinks:pending');
258295
if (pendingDeepLink?.url == null) return;
259296
const link = parseDeepLinkUri(Uri.parse(pendingDeepLink.url));
260297
if (link == null) return;
@@ -1061,13 +1098,16 @@ export class DeepLinkService implements Disposable {
10611098
action = DeepLinkServiceAction.RepoOpening;
10621099
if (!(repoOpenLocation === 'addToWorkspace' && (workspace.workspaceFolders?.length || 0) > 1)) {
10631100
// Deep link will resolve in a different service instance
1064-
await this.container.storage.store('deepLinks:pending', {
1065-
url: this._context.url,
1066-
repoPath: repoOpenUri.toString(),
1067-
targetSha: this._context.targetSha,
1068-
secondaryTargetSha: this._context.secondaryTargetSha,
1069-
useProgress: useProgress,
1070-
});
1101+
await this.container.storage.storeSecret(
1102+
'deepLinks:pending',
1103+
JSON.stringify({
1104+
url: this._context.url,
1105+
repoPath: repoOpenUri.toString(),
1106+
targetSha: this._context.targetSha,
1107+
secondaryTargetSha: this._context.secondaryTargetSha,
1108+
useProgress: useProgress,
1109+
}),
1110+
);
10711111
action = DeepLinkServiceAction.DeepLinkStored;
10721112
}
10731113

@@ -1349,9 +1389,11 @@ export class DeepLinkService implements Disposable {
13491389

13501390
// Storing link info in case the switch causes a new window to open
13511391
const onWorkspaceChanging = async (isNewWorktree?: boolean) =>
1352-
this.container.storage.store(
1392+
this.container.storage.storeSecret(
13531393
'deepLinks:pending',
1354-
isNewWorktree ? pendingDeepLink : { ...pendingDeepLink, url: nonPrUrl },
1394+
isNewWorktree
1395+
? JSON.stringify(pendingDeepLink)
1396+
: JSON.stringify({ ...pendingDeepLink, url: nonPrUrl }),
13551397
);
13561398

13571399
await executeGitCommand({
@@ -1406,7 +1448,7 @@ export class DeepLinkService implements Disposable {
14061448
}
14071449
case DeepLinkServiceState.OpenInspect: {
14081450
// If we arrive at this step, clear any stored data used for the "new window" option
1409-
await this.container.storage.delete('deepLinks:pending');
1451+
await this.container.storage.deleteSecret('deepLinks:pending');
14101452
if (!repo) {
14111453
action = DeepLinkServiceAction.DeepLinkErrored;
14121454
message = 'Missing repository.';

src/webviews/home/homeWebview.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,8 +1236,17 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
12361236
subcommand: 'open',
12371237
repo: defaultWorktree.repoPath,
12381238
worktree: defaultWorktree,
1239-
onWorkspaceChanging: async (_isNewWorktree?: boolean) =>
1240-
this.container.storage.store('deepLinks:pending', deleteBranchDeepLink),
1239+
onWorkspaceChanging: async (_isNewWorktree?: boolean) => {
1240+
await this.container.storage.storeSecret(
1241+
'deepLinks:pending',
1242+
JSON.stringify(deleteBranchDeepLink),
1243+
);
1244+
// Close the current window. This should only occur if there was already a different
1245+
// window open for the default worktree.
1246+
setTimeout(() => {
1247+
void executeCoreCommand('workbench.action.closeWindow');
1248+
}, 2000);
1249+
},
12411250
worktreeDefaultOpen: 'current',
12421251
},
12431252
});

0 commit comments

Comments
 (0)