diff --git a/src/github/githubRepository.ts b/src/github/githubRepository.ts index cd825eae00..7ed48ec22f 100644 --- a/src/github/githubRepository.ts +++ b/src/github/githubRepository.ts @@ -437,15 +437,22 @@ export class GitHubRepository extends Disposable { Logger.debug(`Fetch metadata - enter`, this.id); const { remote } = await this.ensure(); - this._metadata = this.getMetadataForRepo(remote.owner, remote.repositoryName).catch(e => { - if ((getErrorCode(e) === '404') && !isSamlError(e) && !this._isInaccessible) { - this._isInaccessible = true; - Logger.warn(`Repository ${remote.owner}/${remote.repositoryName} from remote ${remote.remoteName} in workspace folder ${this.rootUri.fsPath} returned HTTP 404 and will be skipped for this session.`, this.id); + const metadata = this.getMetadataForRepo(remote.owner, remote.repositoryName).catch(e => { + if (this._metadata === metadata) { + if ((getErrorCode(e) === '404') && !isSamlError(e)) { + if (!this._isInaccessible) { + this._isInaccessible = true; + Logger.warn(`Repository ${remote.owner}/${remote.repositoryName} from remote ${remote.remoteName} in workspace folder ${this.rootUri.fsPath} returned HTTP 404 and will be skipped for this session.`, this.id); + } + } else { + this._metadata = undefined; + } } throw e; }); + this._metadata = metadata; Logger.debug(`Fetch metadata ${remote.owner}/${remote.repositoryName} - done`, this.id); - return this._metadata; + return metadata; } /** diff --git a/src/test/github/githubRepository.test.ts b/src/test/github/githubRepository.test.ts index 946c2f7c54..515a93764a 100644 --- a/src/test/github/githubRepository.test.ts +++ b/src/test/github/githubRepository.test.ts @@ -56,6 +56,25 @@ describe('GitHubRepository', function () { }); }); + describe('getMetadata', function () { + it('retries after a transient failure and caches the successful result', async function () { + const url = 'https://github.com/some/repo'; + const remote = new GitHubRemote('origin', url, new Protocol(url), GitHubServerType.GitHubDotCom); + const repo = new GitHubRepository(1, remote, Uri.file('/workspaces/repo'), credentialStore, telemetry); + sinon.stub(repo, 'ensure').resolves(repo); + const fetchMetadata = sinon.stub(repo as any, 'getMetadataForRepo'); + const error = new Error('Connect Timeout Error'); + const metadata = { name: 'repo', owner: { login: 'some' } }; + fetchMetadata.onFirstCall().rejects(error); + fetchMetadata.onSecondCall().resolves(metadata); + + await assert.rejects(repo.getMetadata(), candidate => candidate === error); + assert.strictEqual(await repo.getMetadata(), metadata); + assert.strictEqual(await repo.getMetadata(), metadata); + assert.strictEqual(fetchMetadata.callCount, 2); + }); + }); + describe('resolveRemote', function () { beforeEach(function () { sinon.stub(credentialStore, 'isAuthenticated').returns(true);