src/desktop/gitlab/gitlab_platform_desktop.ts (82 lines of code) (raw):
import * as vscode from 'vscode';
import { getActiveProject, getActiveProjectOrSelectOne } from '../commands/run_with_valid_project';
import {
GitLabPlatformForAccount,
GitLabPlatformManager,
} from '../../common/platform/gitlab_platform';
import { Account, serializeAccountSafe } from '../../common/platform/gitlab_account';
import { getWorkspaceAccountManager } from '../accounts/workspace_account_manager';
import { accountService } from '../accounts/account_service';
import { log } from '../../common/log';
import { extensionConfigurationService } from '../../common/utils/extension_configuration_service';
import { doNotAwait } from '../../common/utils/do_not_await';
import { getGitLabServiceForAccount } from './get_gitlab_service';
import { ProjectInRepository } from './new_project';
import { getUserAgentHeader } from './http/get_user_agent_header';
import { getProjectRepository } from './gitlab_project_repository';
let inconsistencyWarningShown = false;
const getProjectInRepository = async (userInitiated: boolean) => {
let projectInRepository: ProjectInRepository | undefined;
if (userInitiated) {
projectInRepository = await getActiveProjectOrSelectOne();
} else {
projectInRepository = getActiveProject();
}
return projectInRepository;
};
function createGitLabPlatformForAccount(account: Account): GitLabPlatformForAccount {
return {
type: 'account',
account,
project: undefined,
fetchFromApi: async req => getGitLabServiceForAccount(account).fetchFromApi(req),
connectToCable: async () => getGitLabServiceForAccount(account).connectToCable(),
getUserAgentHeader,
};
}
export const gitlabPlatformManagerDesktop: GitLabPlatformManager = {
getForActiveProject: async userInitiated => {
const projectInRepository = await getProjectInRepository(userInitiated);
if (!projectInRepository) {
return undefined;
}
const upToDateAccount = await accountService.getAccount(projectInRepository.account.id);
if (!upToDateAccount) {
log.error(
`[GitLabPlatformManagerDesktop][auth] The account ${projectInRepository.account.id} no longer exists`,
);
return undefined;
}
if (upToDateAccount.token !== projectInRepository.account.token) {
log.warn(
`[auth] The token stored in project repository is out of date with the main VS Code storage` +
`ProjectRepository account ${serializeAccountSafe(projectInRepository.account)}` +
`VS Code storage account ${serializeAccountSafe(upToDateAccount)}`,
);
if (extensionConfigurationService.getConfiguration().debug && !inconsistencyWarningShown) {
inconsistencyWarningShown = true;
doNotAwait(
vscode.window.showWarningMessage(
'We noticed and fixed inconsistency in the GitLab account cache. The extension will continue working as expected. ' +
'We cannot reliably reproduce this inconsistency, please help us by adding a comment to [this issue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/1935) ' +
'with [your logs](https://docs.gitlab.com/editor_extensions/visual_studio_code/troubleshooting/#view-log-files) from all running VS Code windows',
),
);
}
}
return {
type: 'project',
account: upToDateAccount,
project: projectInRepository.project,
fetchFromApi: async req => getGitLabServiceForAccount(upToDateAccount).fetchFromApi(req),
connectToCable: async () => getGitLabServiceForAccount(upToDateAccount).connectToCable(),
getUserAgentHeader,
};
},
getForActiveAccount: async () => {
const { activeAccount } = getWorkspaceAccountManager();
return activeAccount && createGitLabPlatformForAccount(activeAccount);
},
// This is tricky
// The project repository caches accounts.
// When account changes, project repository updates this cache, but it takes long time
// because it has to do several API requests. Until the API calls are done, the account cache is stale.
// If we listened on accountChange here, results of the platform.getForActiveProject() method wouldn't
// be guaranteed to have the up-to-date account because the platform uses project repository.
// That's why we have to listen on project repository and not on account changes.
// See sequence diagrams: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/1174#note_1658575653
onAccountChange: listener =>
vscode.Disposable.from(getProjectRepository().onProjectChange(() => listener())),
};