Skip to content

Commit

Permalink
Caches and stores Bitbucket inermediate data e.g. workspaces and repos
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeibbb committed Feb 24, 2025
1 parent cae3faa commit 84e8e04
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/constants.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export type GlobalStorage = {
[key in `azure:${string}:organizations`]: Stored<StoredAzureOrganization[] | undefined>;
} & {
[key in `azure:${string}:projects`]: Stored<StoredAzureProject[] | undefined>;
} & { [key in `bitbucket:${string}:account`]: Stored<StoredBitbucketAccount | undefined> } & {
[key in `bitbucket:${string}:workspaces`]: Stored<StoredBitbucketWorkspace[] | undefined>;
} & {
[key in `bitbucket:${string}:repositories`]: Stored<StoredBitbucketRepository[] | undefined>;
};

export type StoredIntegrationConfigurations = Record<string, StoredConfiguredIntegrationDescriptor[] | undefined>;
Expand Down Expand Up @@ -245,6 +249,28 @@ export interface StoredAzureProject {
resourceName: string;
}

export interface StoredBitbucketAccount {
id: string;
name: string | undefined;
username: string | undefined;
email: string | undefined;
avatarUrl: string | undefined;
}

export interface StoredBitbucketWorkspace {
key: string;
id: string;
name: string;
slug: string;
}

export interface StoredBitbucketRepository {
key: string;
owner: string;
name: string;
resourceId: string;
}

export interface StoredAvatar {
uri: string;
timestamp: number;
Expand Down
74 changes: 74 additions & 0 deletions src/plus/integrations/providers/bitbucket.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AuthenticationSession, CancellationToken } from 'vscode';
import { md5 } from '@env/crypto';
import { HostingIntegrationId } from '../../../constants.integrations';
import type { Account } from '../../../git/models/author';
import type { DefaultBranch } from '../../../git/models/defaultBranch';
Expand Down Expand Up @@ -33,6 +34,7 @@ interface BitbucketWorkspaceDescriptor extends ResourceDescriptor {
}

interface BitbucketRemoteRepositoryDescriptor extends ResourceDescriptor {
resourceId: string;
owner: string;
name: string;
cloneUrlHttps?: string;
Expand Down Expand Up @@ -243,6 +245,7 @@ export class BitbucketIntegration extends HostingIntegration<
`${accessToken}:${resource.id}`,
resourceRepos.map(r => ({
id: `${r.owner}/${r.name}`,
resourceId: r.owner,
owner: r.owner,
name: r.name,
key: `${r.owner}/${r.name}`,
Expand Down Expand Up @@ -307,6 +310,77 @@ export class BitbucketIntegration extends HostingIntegration<
remotePullRequest.graphQLId = remotePullRequest.id;
return fromProviderPullRequest(remotePullRequest, this);
}

protected override async providerOnConnect(): Promise<void> {
if (this._session == null) return;

const accountStorageKey = md5(this._session.accessToken);

const storedAccount = this.container.storage.get(`bitbucket:${accountStorageKey}:account`);
const storedWorkspaces = this.container.storage.get(`bitbucket:${accountStorageKey}:workspaces`);
const storedRepositories = this.container.storage.get(`bitbucket:${accountStorageKey}:repositories`);

let account: Account | undefined = storedAccount?.data ? { ...storedAccount.data, provider: this } : undefined;
let workspaces = storedWorkspaces?.data?.map(o => ({ ...o }));
let repositories = storedRepositories?.data?.map(p => ({ ...p }));

if (storedAccount == null) {
account = await this.getProviderCurrentAccount(this._session);
if (account != null) {
// Clear all other stored workspaces and repositories and accounts when our session changes
await this.container.storage.deleteWithPrefix('bitbucket');
await this.container.storage.store(`bitbucket:${accountStorageKey}:account`, {
v: 1,
timestamp: Date.now(),
data: {
id: account.id,
name: account.name,
email: account.email,
avatarUrl: account.avatarUrl,
username: account.username,
},
});
}
}
this._accounts ??= new Map<string, Account | undefined>();
this._accounts.set(this._session.accessToken, account);

if (storedWorkspaces == null) {
workspaces = await this.getProviderResourcesForUser(this._session, true);
await this.container.storage.store(`bitbucket:${accountStorageKey}:workspaces`, {
v: 1,
timestamp: Date.now(),
data: workspaces,
});
}
this._workspaces ??= new Map<string, BitbucketWorkspaceDescriptor[] | undefined>();
this._workspaces.set(this._session.accessToken, workspaces);

if (storedRepositories == null && workspaces?.length) {
repositories = await this.getProviderProjectsForResources(this._session, workspaces);
await this.container.storage.store(`bitbucket:${accountStorageKey}:repositories`, {
v: 1,
timestamp: Date.now(),
data: repositories,
});
}
this._repositories ??= new Map<string, BitbucketRemoteRepositoryDescriptor[] | undefined>();
for (const repository of repositories ?? []) {
const resourceKey = `${this._session.accessToken}:${repository.resourceId}`;
const repos = this._repositories.get(resourceKey);
if (repos == null) {
this._repositories.set(resourceKey, [repository]);
} else if (!repos.some(r => r.key === repository.key)) {
repos.push(repository);
}
}
}

protected override providerOnDisconnect(): void {
this._accounts = undefined;
this._workspaces = undefined;
this._repositories = undefined;
}
}

const bitbucketCloudDomainRegex = /^bitbucket\.org$/i;
Expand Down

0 comments on commit 84e8e04

Please sign in to comment.