Browse Source

fix(1.67): update patches (#1066)

Baptiste Augrain 3 years ago
parent
commit
0932463dfb

+ 3 - 3
.github/workflows/linux.yml

@@ -27,9 +27,9 @@ jobs:
         - vscode_arch: arm64
           npm_arch: arm64
           image: vscodium/vscodium-linux-build-agent:stretch-arm64
-        - vscode_arch: armhf
-          npm_arch: armv7l
-          image: vscodium/vscodium-linux-build-agent:stretch-armhf
+        # - vscode_arch: armhf
+        #   npm_arch: armv7l
+        #   image: vscodium/vscodium-linux-build-agent:stretch-armhf
 
     steps:
       - uses: actions/checkout@v3

+ 6 - 3
.github/workflows/windows.yml

@@ -20,7 +20,10 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        vscode_arch: [x64, ia32, arm64]
+        vscode_arch:
+          - x64
+          # - ia32
+          - arm64
 
     steps:
       - uses: actions/checkout@v3
@@ -33,10 +36,10 @@ jobs:
       - name: Install Yarn
         run: npm install -g yarn
 
-      - name: Setup Python 2
+      - name: Setup Python 3
         uses: actions/setup-python@v3
         with:
-          python-version: '2.x'
+          python-version: '3.x'
 
       - name: Clone VSCode repo
         run: ./get_repo.sh

+ 1 - 0
build.sh

@@ -4,6 +4,7 @@ set -ex
 
 if [[ "${SHOULD_BUILD}" == "yes" ]]; then
   npm config set scripts-prepend-node-path true
+  npm config set node_gyp
 
   echo "MS_COMMIT: ${MS_COMMIT}"
 

+ 1 - 1
docs/build.md

@@ -40,7 +40,7 @@
 - sed
 - 7z
 - [WiX Toolset](http://wixtoolset.org/releases/)
-- python2
+- python3
 - 'Tools for Native Modules' from official Node.js installer
 
 ## <a id="build-scripts"></a>Build Scripts

+ 36 - 0
patches/fix-build-rpm.patch

@@ -0,0 +1,36 @@
+diff --git a/build/linux/rpm/dependencies-generator.js b/build/linux/rpm/dependencies-generator.js
+index 1d91eb8..ed6b775 100644
+--- a/build/linux/rpm/dependencies-generator.js
++++ b/build/linux/rpm/dependencies-generator.js
+@@ -16,7 +16,7 @@ const dep_lists_1 = require("./dep-lists");
+ // If true, we fail the build if there are new dependencies found during that task.
+ // The reference dependencies, which one has to update when the new dependencies
+ // are valid, are in dep-lists.ts
+-const FAIL_BUILD_FOR_NEW_DEPENDENCIES = true;
++const FAIL_BUILD_FOR_NEW_DEPENDENCIES = false;
+ function getDependencies(buildDir, applicationName, arch) {
+     // Get the files for which we want to find dependencies.
+     const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
+diff --git a/build/linux/rpm/dependencies-generator.ts b/build/linux/rpm/dependencies-generator.ts
+index 95953ec..f5ffc2e 100644
+--- a/build/linux/rpm/dependencies-generator.ts
++++ b/build/linux/rpm/dependencies-generator.ts
+@@ -18,7 +18,7 @@ import { ArchString } from './types';
+ // If true, we fail the build if there are new dependencies found during that task.
+ // The reference dependencies, which one has to update when the new dependencies
+ // are valid, are in dep-lists.ts
+-const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true;
++const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = false;
+ 
+ export function getDependencies(buildDir: string, applicationName: string, arch: ArchString): string[] {
+ 	// Get the files for which we want to find dependencies.
+diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template
+index 5b7eadb..87c914d 100644
+--- a/resources/linux/rpm/code.spec.template
++++ b/resources/linux/rpm/code.spec.template
+@@ -74,3 +74,5 @@ update-mime-database /usr/share/mime &> /dev/null || :
+ /usr/share/pixmaps/@@ICON@@.png
+ /usr/share/bash-completion/completions/@@NAME@@
+ /usr/share/zsh/site-functions/_@@NAME@@
++
++%config(noreplace) /usr/share/@@NAME@@/resources/app/product.json

+ 0 - 15
patches/fix-builtin-extensions.patch

@@ -1,15 +0,0 @@
-diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
-index 2b0a0fa..499cff4 100644
---- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
-+++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
-@@ -206,6 +206,10 @@ export class Extension implements IExtension {
- 		if (!this.gallery || !this.local) {
- 			return false;
- 		}
-+		// Do not allow updating system extensions
-+		if (this.type === ExtensionType.System) {
-+			return false;
-+		}
- 		if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
- 			return false;
- 		}

+ 0 - 8
patches/fix-rpm-spec.patch

@@ -1,8 +0,0 @@
---- vscode/resources/linux/rpm/code.spec.template	2021-03-02 19:26:53.000000000 +0100
-+++ vscode/resources/linux/rpm/code.spec.template.new	2021-03-02 19:28:12.000000000 +0100
-@@ -69,3 +69,5 @@
- /usr/share/pixmaps/@@ICON@@.png
- /usr/share/bash-completion/completions/@@NAME@@
- /usr/share/zsh/site-functions/_@@NAME@@
-+
-+%config(noreplace) /usr/share/@@NAME@@/resources/app/product.json

+ 306 - 196
patches/use-github-pat.patch

@@ -1,9 +1,12 @@
 diff --git a/extensions/github-authentication/src/githubServer.ts b/extensions/github-authentication/src/githubServer.ts
-index 49a523b..d68588e 100644
+index c366ff3..75f32da 100644
 --- a/extensions/github-authentication/src/githubServer.ts
 +++ b/extensions/github-authentication/src/githubServer.ts
-@@ -6,23 +6,14 @@
- import * as nls from 'vscode-nls';
+@@ -3,27 +3,13 @@
+  *  Licensed under the MIT License. See License.txt in the project root for license information.
+  *--------------------------------------------------------------------------------------------*/
+ 
+-import * as nls from 'vscode-nls';
  import * as vscode from 'vscode';
  import fetch, { Response } from 'node-fetch';
 -import { v4 as uuid } from 'uuid';
@@ -12,150 +15,322 @@ index 49a523b..d68588e 100644
  import { AuthProviderType } from './github';
  import { Log } from './common/logger';
 -import { isSupportedEnvironment } from './common/env';
- 
- const localize = nls.loadMessageBundle();
- const CLIENT_ID = '01ab8ac9400c4e429b23';
+-import { LoopbackAuthServer } from './authServer';
+-import path = require('path');
+-
+-const localize = nls.loadMessageBundle();
+-const CLIENT_ID = '01ab8ac9400c4e429b23';
 -const GITHUB_AUTHORIZE_URL = 'https://github.com/login/oauth/authorize';
 -// TODO: change to stable when that happens
 -const GITHUB_TOKEN_URL = 'https://vscode.dev/codeExchangeProxyEndpoints/github/login/oauth/access_token';
- const NETWORK_ERROR = 'network error';
+-const NETWORK_ERROR = 'network error';
  
 -const REDIRECT_URL_STABLE = 'https://vscode.dev/redirect';
 -const REDIRECT_URL_INSIDERS = 'https://insiders.vscode.dev/redirect';
--
++const NETWORK_ERROR = 'network error';
+ 
  class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler {
  	constructor(private readonly Logger: Log) {
- 		super();
-@@ -110,10 +101,7 @@ async function getUserInfo(token: string, serverUri: vscode.Uri, logger: Log): P
- export class GitHubServer implements IGitHubServer {
+@@ -43,14 +29,6 @@ export interface IGitHubServer extends vscode.Disposable {
+ 	friendlyName: string;
+ 	type: AuthProviderType;
+ }
+-
+-interface IGitHubDeviceCodeResponse {
+-	device_code: string;
+-	user_code: string;
+-	verification_uri: string;
+-	interval: number;
+-}
+-
+ async function getScopes(token: string, serverUri: vscode.Uri, logger: Log): Promise<string[]> {
+ 	try {
+ 		logger.info('Getting token scopes...');
+@@ -118,23 +96,11 @@ export class GitHubServer implements IGitHubServer {
  	friendlyName = 'GitHub';
  	type = AuthProviderType.github;
--	private _onDidManuallyProvideToken = new vscode.EventEmitter<string | undefined>();
  
 -	private _pendingNonces = new Map<string, string[]>();
 -	private _codeExchangePromises = new Map<string, { promise: Promise<string>; cancel: vscode.EventEmitter<void> }>();
  	private _disposable: vscode.Disposable;
  	private _uriHandler = new UriEventHandler(this._logger);
+-	private readonly getRedirectEndpoint: Thenable<string>;
  
-@@ -125,87 +113,31 @@ export class GitHubServer implements IGitHubServer {
- 		this._disposable.dispose();
+-	constructor(private readonly _supportDeviceCodeFlow: boolean, private readonly _logger: Log, private readonly _telemetryReporter: ExperimentationTelemetry) {
++	constructor(_supportDeviceCodeFlow: boolean, private readonly _logger: Log, private readonly _telemetryReporter: ExperimentationTelemetry) {
+ 		this._disposable = vscode.window.registerUriHandler(this._uriHandler);
+-
+-		this.getRedirectEndpoint = vscode.commands.executeCommand<{ [providerId: string]: string } | undefined>('workbench.getCodeExchangeProxyEndpoints').then((proxyEndpoints) => {
+-			// If we are running in insiders vscode.dev, then ensure we use the redirect route on that.
+-			let redirectUri = REDIRECT_URL_STABLE;
+-			if (proxyEndpoints?.github && new URL(proxyEndpoints.github).hostname === 'insiders.vscode.dev') {
+-				redirectUri = REDIRECT_URL_INSIDERS;
+-			}
+-			return redirectUri;
+-		});
  	}
  
--	// TODO@joaomoreno TODO@TylerLeonhardt
--	private async isNoCorsEnvironment(): Promise<boolean> {
--		const uri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/dummy`));
--		return (uri.scheme === 'https' && /^((insiders\.)?vscode|github)\./.test(uri.authority)) || (uri.scheme === 'http' && /^localhost/.test(uri.authority));
--	}
--
- 	public async login(scopes: string): Promise<string> {
- 		this._logger.info(`Logging in for the following scopes: ${scopes}`);
+ 	dispose() {
+@@ -152,181 +118,17 @@ export class GitHubServer implements IGitHubServer {
  
+ 		// Used for showing a friendlier message to the user when the explicitly cancel a flow.
+ 		let userCancelled: boolean | undefined;
+-		const yes = localize('yes', "Yes");
+-		const no = localize('no', "No");
+-		const promptToContinue = async () => {
+-			if (userCancelled === undefined) {
+-				// We haven't had a failure yet so wait to prompt
+-				return;
+-			}
+-			const message = userCancelled
+-				? localize('userCancelledMessage', "Having trouble logging in? Would you like to try a different way?")
+-				: localize('otherReasonMessage', "You have not yet finished authorizing this extension to use GitHub. Would you like to keep trying?");
+-			const result = await vscode.window.showWarningMessage(message, yes, no);
+-			if (result !== yes) {
+-				throw new Error('Cancelled');
+-			}
+-		};
+-
 -		const nonce = uuid();
 -		const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate?nonce=${encodeURIComponent(nonce)}`));
 -
--		if (!isSupportedEnvironment(callbackUri)) {
--			const token = this._supportDeviceCodeFlow
--				? await this.doDeviceCodeFlow(scopes)
--				: await vscode.window.showInputBox({ prompt: 'GitHub Personal Access Token', ignoreFocusOut: true });
-+		const token = this._supportDeviceCodeFlow
-+			? await this.doDeviceCodeFlow(scopes)
-+			: await vscode.window.showInputBox({ prompt: 'GitHub Personal Access Token', ignoreFocusOut: true });
- 
--			if (!token) { throw new Error('No token provided'); }
-+		if (!token) { throw new Error('No token provided'); }
- 
--			const tokenScopes = await getScopes(token, this.getServerUri('/'), this._logger); // Example: ['repo', 'user']
--			const scopesList = scopes.split(' '); // Example: 'read:user repo user:email'
--			if (!scopesList.every(scope => {
--				const included = tokenScopes.includes(scope);
--				if (included || !scope.includes(':')) {
--					return included;
--				}
+-		const supported = isSupportedEnvironment(callbackUri);
+-		if (supported) {
+-			try {
+-				return await this.doLoginWithoutLocalServer(scopes, nonce, callbackUri);
+-			} catch (e) {
+-				this._logger.error(e);
+-				userCancelled = e.message ?? e === 'User Cancelled';
+-			}
+-		}
 -
--				return scope.split(':').some(splitScopes => {
--					return tokenScopes.includes(splitScopes);
--				});
--			})) {
--				throw new Error(`The provided token does not match the requested scopes: ${scopes}`);
-+		const tokenScopes = await getScopes(token, this.getServerUri('/'), this._logger); // Example: ['repo', 'user']
-+		const scopesList = scopes.split(' '); // Example: 'read:user repo user:email'
-+		if (!scopesList.every(scope => {
-+			const included = tokenScopes.includes(scope);
-+			if (included || !scope.includes(':')) {
-+				return included;
- 			}
+-		// Starting a local server isn't supported in web
+-		if (vscode.env.uiKind === vscode.UIKind.Desktop) {
+-			try {
+-				await promptToContinue();
+-				return await this.doLoginWithLocalServer(scopes);
+-			} catch (e) {
+-				this._logger.error(e);
+-				userCancelled = e.message ?? e === 'User Cancelled';
+-			}
+-		}
  
--			return token;
-+			return scope.split(':').some(splitScopes => {
-+				return tokenScopes.includes(splitScopes);
-+			});
-+		})) {
-+			throw new Error(`The provided token does not match the requested scopes: ${scopes}`);
+-		if (this._supportDeviceCodeFlow) {
+-			try {
+-				await promptToContinue();
+-				return await this.doLoginDeviceCodeFlow(scopes);
+-			} catch (e) {
+-				this._logger.error(e);
+-				userCancelled = e.message ?? e === 'User Cancelled';
+-			}
+-		} else if (!supported) {
+-			try {
+-				await promptToContinue();
+-				return await this.doLoginWithPat(scopes);
+-			} catch (e) {
+-				this._logger.error(e);
+-				userCancelled = e.message ?? e === 'User Cancelled';
+-			}
++		try {
++			return await this.doLoginWithPat(scopes);
++		} catch (e) {
++			this._logger.error(e);
++			userCancelled = e.message ?? e === 'User Cancelled';
  		}
  
--		const existingNonces = this._pendingNonces.get(scopes) || [];
--		this._pendingNonces.set(scopes, [...existingNonces, nonce]);
--
--		const proxyEndpoints: { [providerId: string]: string } | undefined = await vscode.commands.executeCommand('workbench.getCodeExchangeProxyEndpoints');
--		// If we are running in insiders vscode.dev, then ensure we use the redirect route on that.
--		const redirectUri = proxyEndpoints?.github?.includes('https://insiders.vscode.dev') ? REDIRECT_URL_INSIDERS : REDIRECT_URL_STABLE;
--		const searchParams = new URLSearchParams([
--			['client_id', CLIENT_ID],
--			['redirect_uri', redirectUri],
--			['scope', scopes],
--			['state', encodeURIComponent(callbackUri.toString(true))]
--		]);
--		const uri = vscode.Uri.parse(`${GITHUB_AUTHORIZE_URL}?${searchParams.toString()}`);
--
--		return vscode.window.withProgress({
--			location: vscode.ProgressLocation.Window,
--			title: localize('signingIn', " $(mark-github) Signing in to github.com..."),
--		}, async () => {
+ 		throw new Error(userCancelled ? 'Cancelled' : 'No auth flow succeeded.');
+ 	}
+ 
+-	private async doLoginWithoutLocalServer(scopes: string, nonce: string, callbackUri: vscode.Uri): Promise<string> {
+-		this._logger.info(`Trying without local server... (${scopes})`);
+-		return await vscode.window.withProgress<string>({
+-			location: vscode.ProgressLocation.Notification,
+-			title: localize('signingIn', "Signing in to github.com..."),
+-			cancellable: true
+-		}, async (_, token) => {
+-			const existingNonces = this._pendingNonces.get(scopes) || [];
+-			this._pendingNonces.set(scopes, [...existingNonces, nonce]);
+-			const redirectUri = await this.getRedirectEndpoint;
+-			const searchParams = new URLSearchParams([
+-				['client_id', CLIENT_ID],
+-				['redirect_uri', redirectUri],
+-				['scope', scopes],
+-				['state', encodeURIComponent(callbackUri.toString(true))]
+-			]);
+-			const uri = vscode.Uri.parse(`${GITHUB_AUTHORIZE_URL}?${searchParams.toString()}`);
 -			await vscode.env.openExternal(uri);
 -
 -			// Register a single listener for the URI callback, in case the user starts the login process multiple times
 -			// before completing it.
 -			let codeExchangePromise = this._codeExchangePromises.get(scopes);
 -			if (!codeExchangePromise) {
--				codeExchangePromise = promiseFromEvent(this._uriHandler.event, this.exchangeCodeForToken(scopes));
+-				codeExchangePromise = promiseFromEvent(this._uriHandler.event, this.handleUri(scopes));
 -				this._codeExchangePromises.set(scopes, codeExchangePromise);
 -			}
 -
--			return Promise.race([
--				codeExchangePromise.promise,
--				promiseFromEvent<string | undefined, string>(this._onDidManuallyProvideToken.event, (token: string | undefined, resolve, reject): void => {
--					if (!token) {
--						reject('Cancelled');
--					} else {
--						resolve(token);
--					}
--				}).promise,
--				new Promise<string>((_, reject) => setTimeout(() => reject('Cancelled'), 60000))
--			]).finally(() => {
+-			try {
+-				return await Promise.race([
+-					codeExchangePromise.promise,
+-					new Promise<string>((_, reject) => setTimeout(() => reject('Cancelled'), 60000)),
+-					promiseFromEvent<any, any>(token.onCancellationRequested, (_, __, reject) => { reject('User Cancelled'); }).promise
+-				]);
+-			} finally {
 -				this._pendingNonces.delete(scopes);
 -				codeExchangePromise?.cancel.fire();
 -				this._codeExchangePromises.delete(scopes);
--			});
+-			}
 -		});
-+		return token;
- 	}
+-	}
+-
+-	private async doLoginWithLocalServer(scopes: string): Promise<string> {
+-		this._logger.info(`Trying with local server... (${scopes})`);
+-		return await vscode.window.withProgress<string>({
+-			location: vscode.ProgressLocation.Notification,
+-			title: localize('signingInAnotherWay', "Signing in to github.com..."),
+-			cancellable: true
+-		}, async (_, token) => {
+-			const redirectUri = await this.getRedirectEndpoint;
+-			const searchParams = new URLSearchParams([
+-				['client_id', CLIENT_ID],
+-				['redirect_uri', redirectUri],
+-				['scope', scopes],
+-			]);
+-			const loginUrl = `${GITHUB_AUTHORIZE_URL}?${searchParams.toString()}`;
+-			const server = new LoopbackAuthServer(path.join(__dirname, '../media'), loginUrl);
+-			const port = await server.start();
+-
+-			let codeToExchange;
+-			try {
+-				vscode.env.openExternal(vscode.Uri.parse(`http://127.0.0.1:${port}/signin?nonce=${encodeURIComponent(server.nonce)}`));
+-				const { code } = await Promise.race([
+-					server.waitForOAuthResponse(),
+-					new Promise<any>((_, reject) => setTimeout(() => reject('Cancelled'), 60000)),
+-					promiseFromEvent<any, any>(token.onCancellationRequested, (_, __, reject) => { reject('User Cancelled'); }).promise
+-				]);
+-				codeToExchange = code;
+-			} finally {
+-				setTimeout(() => {
+-					void server.stop();
+-				}, 5000);
+-			}
+-
+-			const accessToken = await this.exchangeCodeForToken(codeToExchange);
+-			return accessToken;
+-		});
+-	}
+-
+-	private async doLoginDeviceCodeFlow(scopes: string): Promise<string> {
+-		this._logger.info(`Trying device code flow... (${scopes})`);
+-
+-		// Get initial device code
+-		const uri = `https://github.com/login/device/code?client_id=${CLIENT_ID}&scope=${scopes}`;
+-		const result = await fetch(uri, {
+-			method: 'POST',
+-			headers: {
+-				Accept: 'application/json'
+-			}
+-		});
+-		if (!result.ok) {
+-			throw new Error(`Failed to get one-time code: ${await result.text()}`);
+-		}
+-
+-		const json = await result.json() as IGitHubDeviceCodeResponse;
+-
+-
+-		const modalResult = await vscode.window.showInformationMessage(
+-			localize('code.title', "Your Code: {0}", json.user_code),
+-			{
+-				modal: true,
+-				detail: localize('code.detail', "To finish authenticating, navigate to GitHub and paste in the above one-time code.")
+-			}, 'Copy & Continue to GitHub');
+-
+-		if (modalResult !== 'Copy & Continue to GitHub') {
+-			throw new Error('User Cancelled');
+-		}
+-
+-		await vscode.env.clipboard.writeText(json.user_code);
+-
+-		const uriToOpen = await vscode.env.asExternalUri(vscode.Uri.parse(json.verification_uri));
+-		await vscode.env.openExternal(uriToOpen);
+-
+-		return await this.waitForDeviceCodeAccessToken(json);
+-	}
  
- 	private async doDeviceCodeFlow(scopes: string): Promise<string> {
-@@ -299,57 +231,6 @@ export class GitHubServer implements IGitHubServer {
- 		throw new Error('Cancelled');
+ 	private async doLoginWithPat(scopes: string): Promise<string> {
+ 		this._logger.info(`Trying to retrieve PAT... (${scopes})`);
+@@ -351,118 +153,6 @@ export class GitHubServer implements IGitHubServer {
+ 		return token;
  	}
  
--	private exchangeCodeForToken: (scopes: string) => PromiseAdapter<vscode.Uri, string> =
--		(scopes) => async (uri, resolve, reject) => {
+-	private async waitForDeviceCodeAccessToken(
+-		json: IGitHubDeviceCodeResponse,
+-	): Promise<string> {
+-		return await vscode.window.withProgress<string>({
+-			location: vscode.ProgressLocation.Notification,
+-			cancellable: true,
+-			title: localize(
+-				'progress',
+-				"Open [{0}]({0}) in a new tab and paste your one-time code: {1}",
+-				json.verification_uri,
+-				json.user_code)
+-		}, async (_, token) => {
+-			const refreshTokenUri = `https://github.com/login/oauth/access_token?client_id=${CLIENT_ID}&device_code=${json.device_code}&grant_type=urn:ietf:params:oauth:grant-type:device_code`;
+-
+-			// Try for 2 minutes
+-			const attempts = 120 / json.interval;
+-			for (let i = 0; i < attempts; i++) {
+-				await new Promise(resolve => setTimeout(resolve, json.interval * 1000));
+-				if (token.isCancellationRequested) {
+-					throw new Error('User Cancelled');
+-				}
+-				let accessTokenResult;
+-				try {
+-					accessTokenResult = await fetch(refreshTokenUri, {
+-						method: 'POST',
+-						headers: {
+-							Accept: 'application/json'
+-						}
+-					});
+-				} catch {
+-					continue;
+-				}
+-
+-				if (!accessTokenResult.ok) {
+-					continue;
+-				}
+-
+-				const accessTokenJson = await accessTokenResult.json();
+-
+-				if (accessTokenJson.error === 'authorization_pending') {
+-					continue;
+-				}
+-
+-				if (accessTokenJson.error) {
+-					throw new Error(accessTokenJson.error_description);
+-				}
+-
+-				return accessTokenJson.access_token;
+-			}
+-
+-			throw new Error('Cancelled');
+-		});
+-	}
+-
+-	private handleUri: (scopes: string) => PromiseAdapter<vscode.Uri, string> =
+-		(scopes) => (uri, resolve, reject) => {
 -			const query = new URLSearchParams(uri.query);
 -			const code = query.get('code');
--
--			const acceptedNonces = this._pendingNonces.get(scopes) || [];
 -			const nonce = query.get('nonce');
+-			if (!code) {
+-				reject(new Error('No code'));
+-				return;
+-			}
 -			if (!nonce) {
--				this._logger.error('No nonce in response.');
+-				reject(new Error('No nonce'));
 -				return;
 -			}
+-
+-			const acceptedNonces = this._pendingNonces.get(scopes) || [];
 -			if (!acceptedNonces.includes(nonce)) {
 -				// A common scenario of this happening is if you:
 -				// 1. Trigger a sign in with one set of scopes
@@ -166,85 +341,42 @@ index 49a523b..d68588e 100644
 -				return;
 -			}
 -
--			this._logger.info('Exchanging code for token...');
--
--			const proxyEndpoints: { [providerId: string]: string } | undefined = await vscode.commands.executeCommand('workbench.getCodeExchangeProxyEndpoints');
--			const endpointUrl = proxyEndpoints?.github ? `${proxyEndpoints.github}login/oauth/access_token` : GITHUB_TOKEN_URL;
--
--			try {
--				const body = `code=${code}`;
--				const result = await fetch(endpointUrl, {
--					method: 'POST',
--					headers: {
--						Accept: 'application/json',
--						'Content-Type': 'application/x-www-form-urlencoded',
--						'Content-Length': body.toString()
--
--					},
--					body
--				});
--
--				if (result.ok) {
--					const json = await result.json();
--					this._logger.info('Token exchange success!');
--					resolve(json.access_token);
--				} else {
--					reject(result.statusText);
--				}
--			} catch (ex) {
--				reject(ex);
--			}
+-			resolve(this.exchangeCodeForToken(code));
 -		};
 -
- 	private getServerUri(path: string = '') {
- 		const apiUri = vscode.Uri.parse('https://api.github.com');
- 		return vscode.Uri.parse(`${apiUri.scheme}://${apiUri.authority}${path}`);
-@@ -359,44 +240,7 @@ export class GitHubServer implements IGitHubServer {
- 		return getUserInfo(token, this.getServerUri('/user'), this._logger);
- 	}
- 
--	public async sendAdditionalTelemetryInfo(token: string): Promise<void> {
--		if (!vscode.env.isTelemetryEnabled) {
--			return;
--		}
--		const nocors = await this.isNoCorsEnvironment();
+-	private async exchangeCodeForToken(code: string): Promise<string> {
+-		this._logger.info('Exchanging code for token...');
 -
--		if (nocors) {
--			return;
--		}
+-		const proxyEndpoints: { [providerId: string]: string } | undefined = await vscode.commands.executeCommand('workbench.getCodeExchangeProxyEndpoints');
+-		const endpointUrl = proxyEndpoints?.github ? `${proxyEndpoints.github}login/oauth/access_token` : GITHUB_TOKEN_URL;
 -
--		try {
--			const result = await fetch('https://education.github.com/api/user', {
--				headers: {
--					Authorization: `token ${token}`,
--					'faculty-check-preview': 'true',
--					'User-Agent': 'Visual-Studio-Code'
--				}
--			});
+-		const body = `code=${code}`;
+-		const result = await fetch(endpointUrl, {
+-			method: 'POST',
+-			headers: {
+-				Accept: 'application/json',
+-				'Content-Type': 'application/x-www-form-urlencoded',
+-				'Content-Length': body.toString()
 -
--			if (result.ok) {
--				const json: { student: boolean; faculty: boolean } = await result.json();
--
--				/* __GDPR__
--					"session" : {
--						"isEdu": { "classification": "NonIdentifiableDemographicInfo", "purpose": "FeatureInsight" }
--					}
--				*/
--				this._telemetryReporter.sendTelemetryEvent('session', {
--					isEdu: json.student
--						? 'student'
--						: json.faculty
--							? 'faculty'
--							: 'none'
--				});
--			}
--		} catch (e) {
--			// No-op
+-			},
+-			body
+-		});
+-
+-		if (result.ok) {
+-			const json = await result.json();
+-			this._logger.info('Token exchange success!');
+-			return json.access_token;
+-		} else {
+-			const text = await result.text();
+-			const error = new Error(text);
+-			error.name = 'GitHubTokenExchangeError';
+-			throw error;
 -		}
-+	public async sendAdditionalTelemetryInfo(_: string): Promise<void> {
- 	}
- 
- 	public async checkEnterpriseVersion(token: string): Promise<void> {
+-	}
+-
+ 	private getServerUri(path: string = '') {
+ 		const apiUri = vscode.Uri.parse('https://api.github.com');
+ 		return vscode.Uri.parse(`${apiUri.scheme}://${apiUri.authority}${path}`);
 diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
 index 36647e6..55e722b 100644
 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
@@ -259,32 +391,10 @@ index 36647e6..55e722b 100644
  			menus.push(noAccountsAvailableAction);
  		}
 diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts
-index 5f7431d..278cd3d 100644
+index f543021..ad40bc3 100644
 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts
 +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts
-@@ -13,7 +13,6 @@ import { isString } from 'vs/base/common/types';
- import * as nls from 'vs/nls';
- import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
- import { CommandsRegistry } from 'vs/platform/commands/common/commands';
--import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
- import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
- import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
- import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
-@@ -197,13 +196,6 @@ export class AuthenticationService extends Disposable implements IAuthentication
- 		@IQuickInputService private readonly quickInputService: IQuickInputService
- 	) {
- 		super();
--		this._placeholderMenuItem = MenuRegistry.appendMenuItem(MenuId.AccountsContext, {
--			command: {
--				id: 'noAuthenticationProviders',
--				title: nls.localize('loading', "Loading..."),
--				precondition: ContextKeyExpr.false()
--			},
--		});
- 
- 		authenticationExtPoint.setHandler((extensions, { added, removed }) => {
- 			added.forEach(point => {
-@@ -272,16 +264,6 @@ export class AuthenticationService extends Disposable implements IAuthentication
+@@ -272,16 +272,6 @@ export class AuthenticationService extends Disposable implements IAuthentication
  				this.removeAccessRequest(id, extensionId);
  			});
  		}