Merge pull request #1639 from github/shati-patel/repo-count

Implement query history label for variant analysis items
This commit is contained in:
Shati Patel
2022-10-24 11:29:09 +01:00
committed by GitHub
8 changed files with 125 additions and 30 deletions

View File

@@ -584,11 +584,3 @@ export async function* walkDirectory(dir: string): AsyncIterableIterator<string>
}
}
}
/**
* Pluralizes a word.
* Example: Returns "N repository" if N is one, "N repositories" otherwise.
*/
export function pluralize(numItems: number | undefined, singular: string, plural: string): string {
return numItems ? `${numItems} ${numItems === 1 ? singular : plural}` : '';
}

View File

@@ -2,11 +2,11 @@ import { env } from 'vscode';
import * as path from 'path';
import { QueryHistoryConfig } from './config';
import { LocalQueryInfo } from './query-results';
import { getRawQueryName, QueryHistoryInfo } from './query-history-info';
import { buildRepoLabel, getRawQueryName, QueryHistoryInfo } from './query-history-info';
import { RemoteQueryHistoryItem } from './remote-queries/remote-query-history-item';
import { pluralize } from './helpers';
import { VariantAnalysisHistoryItem } from './remote-queries/variant-analysis-history-item';
import { assertNever } from './pure/helpers-pure';
import { pluralize } from './pure/word';
interface InterpolateReplacements {
t: string; // Start time
@@ -79,23 +79,12 @@ export class HistoryItemLabelProvider {
};
}
// Return the number of repositories queried if available. Otherwise, use the controller repository name.
private buildRepoLabel(item: RemoteQueryHistoryItem): string {
const repositoryCount = item.remoteQuery.repositoryCount;
if (repositoryCount) {
return pluralize(repositoryCount, 'repository', 'repositories');
}
return `${item.remoteQuery.controllerRepository.owner}/${item.remoteQuery.controllerRepository.name}`;
}
private getRemoteInterpolateReplacements(item: RemoteQueryHistoryItem): InterpolateReplacements {
const resultCount = item.resultCount ? `(${pluralize(item.resultCount, 'result', 'results')})` : '';
return {
t: new Date(item.remoteQuery.executionStartTime).toLocaleString(env.language),
q: `${item.remoteQuery.queryName} (${item.remoteQuery.language})`,
d: this.buildRepoLabel(item),
d: buildRepoLabel(item),
r: resultCount,
s: item.status,
f: path.basename(item.remoteQuery.queryFilePath),
@@ -108,7 +97,7 @@ export class HistoryItemLabelProvider {
return {
t: new Date(item.variantAnalysis.executionStartTime).toLocaleString(env.language),
q: `${item.variantAnalysis.query.name} (${item.variantAnalysis.query.language})`,
d: 'TODO',
d: buildRepoLabel(item),
r: resultCount,
s: item.status,
f: path.basename(item.variantAnalysis.query.filePath),

View File

@@ -0,0 +1,8 @@
/**
* Pluralizes a word.
* Example: Returns "N repository" if N is one, "N repositories" otherwise.
*/
export function pluralize(numItems: number | undefined, singular: string, plural: string): string {
return numItems !== undefined ? `${numItems} ${numItems === 1 ? singular : plural}` : '';
}

View File

@@ -2,6 +2,8 @@ import { RemoteQueryHistoryItem } from './remote-queries/remote-query-history-it
import { VariantAnalysisHistoryItem } from './remote-queries/variant-analysis-history-item';
import { LocalQueryInfo } from './query-results';
import { assertNever } from './pure/helpers-pure';
import { pluralize } from './pure/word';
import { hasRepoScanCompleted } from './remote-queries/shared/variant-analysis';
export type QueryHistoryInfo = LocalQueryInfo | RemoteQueryHistoryItem | VariantAnalysisHistoryItem;
@@ -43,3 +45,22 @@ export function getQueryText(item: QueryHistoryInfo): string {
assertNever(item);
}
}
export function buildRepoLabel(item: RemoteQueryHistoryItem | VariantAnalysisHistoryItem): string {
if (item.t === 'remote') {
// Return the number of repositories queried if available. Otherwise, use the controller repository name.
const repositoryCount = item.remoteQuery.repositoryCount;
if (repositoryCount) {
return pluralize(repositoryCount, 'repository', 'repositories');
}
return `${item.remoteQuery.controllerRepository.owner}/${item.remoteQuery.controllerRepository.name}`;
} else if (item.t === 'variant-analysis') {
const totalScannedRepositoryCount = item.variantAnalysis.scannedRepos?.length ?? 0;
const completedRepositoryCount = item.variantAnalysis.scannedRepos?.filter(repo => hasRepoScanCompleted(repo)).length ?? 0;
return `${completedRepositoryCount}/${pluralize(totalScannedRepositoryCount, 'repository', 'repositories')}`; // e.g. "2/3 repositories"
} else {
assertNever(item);
}
}

View File

@@ -4,10 +4,7 @@ import * as fs from 'fs-extra';
import { window, commands, Uri, ExtensionContext, QuickPickItem, workspace, ViewColumn } from 'vscode';
import { Credentials } from '../authentication';
import { UserCancellationException } from '../commandRunner';
import {
showInformationMessageWithAction,
pluralize
} from '../helpers';
import { showInformationMessageWithAction } from '../helpers';
import { logger } from '../logging';
import { QueryHistoryManager } from '../query-history';
import { createGist } from './gh-api/gh-actions-api-client';
@@ -16,6 +13,7 @@ import { generateMarkdown } from './remote-queries-markdown-generation';
import { RemoteQuery } from './remote-query';
import { AnalysisResults, sumAnalysesResults } from './shared/analysis-result';
import { RemoteQueryHistoryItem } from './remote-query-history-item';
import { pluralize } from '../pure/word';
/**
* Exports the results of the given or currently-selected remote query.

View File

@@ -11,7 +11,6 @@ import {
showAndLogErrorMessage,
showAndLogInformationMessage,
tryGetQueryMetadata,
pluralize,
tmpDir,
} from '../helpers';
import { Credentials } from '../authentication';
@@ -24,6 +23,7 @@ import { RemoteQuery } from './remote-query';
import { RemoteQuerySubmissionResult } from './remote-query-submission-result';
import { QueryMetadata } from '../pure/interface-types';
import { getErrorMessage, REPO_REGEX } from '../pure/helpers-pure';
import { pluralize } from '../pure/word';
import * as ghApiClient from './gh-api/gh-api-client';
import { getRepositorySelection, isValidSelection, RepositorySelection } from './repository-selection';
import { parseVariantAnalysisQueryLanguage, VariantAnalysisSubmission } from './shared/variant-analysis';

View File

@@ -1,11 +1,13 @@
import { expect } from 'chai';
import { QueryStatus } from '../../src/query-status';
import { getQueryHistoryItemId, getQueryText, getRawQueryName } from '../../src/query-history-info';
import { buildRepoLabel, getQueryHistoryItemId, getQueryText, getRawQueryName } from '../../src/query-history-info';
import { VariantAnalysisHistoryItem } from '../../src/remote-queries/variant-analysis-history-item';
import { createMockVariantAnalysis } from '../../src/vscode-tests/factories/remote-queries/shared/variant-analysis';
import { createMockScannedRepos } from '../../src/vscode-tests/factories/remote-queries/shared/scanned-repositories';
import { createMockLocalQueryInfo } from '../../src/vscode-tests/factories/local-queries/local-query-history-item';
import { createMockRemoteQueryHistoryItem } from '../../src/vscode-tests/factories/remote-queries/remote-query-history-item';
import { VariantAnalysisRepoStatus, VariantAnalysisStatus } from '../../src/remote-queries/shared/variant-analysis';
describe('Query history info', () => {
@@ -18,7 +20,15 @@ describe('Query history info', () => {
status: QueryStatus.InProgress,
completed: false,
historyItemId: 'abc123',
variantAnalysis: createMockVariantAnalysis()
variantAnalysis: createMockVariantAnalysis(
VariantAnalysisStatus.InProgress,
createMockScannedRepos([
VariantAnalysisRepoStatus.Succeeded,
VariantAnalysisRepoStatus.Pending,
VariantAnalysisRepoStatus.InProgress,
VariantAnalysisRepoStatus.Canceled,
])
),
};
describe('getRawQueryName', () => {
@@ -80,4 +90,61 @@ describe('Query history info', () => {
expect(queryText).to.equal(variantAnalysisHistoryItem.variantAnalysis.query.text);
});
});
describe('buildRepoLabel', () => {
describe('repo label for remote query history items', () => {
it('should return controller repo when `repositoryCount` is 0', () => {
const repoLabel = buildRepoLabel(remoteQueryHistoryItem);
const expectedRepoLabel = `${remoteQueryHistoryItem.remoteQuery.controllerRepository.owner}/${remoteQueryHistoryItem.remoteQuery.controllerRepository.name}`;
expect(repoLabel).to.equal(expectedRepoLabel);
});
it('should return number of repositories when `repositoryCount` is non-zero', () => {
const remoteQueryHistoryItem2 = createMockRemoteQueryHistoryItem({repositoryCount: 3});
const repoLabel2 = buildRepoLabel(remoteQueryHistoryItem2);
const expectedRepoLabel2 = '3 repositories';
expect(repoLabel2).to.equal(expectedRepoLabel2);
});
});
describe('repo label for variant analysis history items', () => {
it('should return label when `totalScannedRepositoryCount` is 0', () => {
const variantAnalysisHistoryItem0: VariantAnalysisHistoryItem = {
t: 'variant-analysis',
status: QueryStatus.InProgress,
completed: false,
historyItemId: 'abc123',
variantAnalysis: createMockVariantAnalysis(
VariantAnalysisStatus.InProgress,
createMockScannedRepos([])
),
};
const repoLabel0 = buildRepoLabel(variantAnalysisHistoryItem0);
expect(repoLabel0).to.equal('0/0 repositories');
});
it('should return label when `totalScannedRepositoryCount` is 1', () => {
const variantAnalysisHistoryItem1: VariantAnalysisHistoryItem = {
t: 'variant-analysis',
status: QueryStatus.InProgress,
completed: false,
historyItemId: 'abc123',
variantAnalysis: createMockVariantAnalysis(
VariantAnalysisStatus.InProgress,
createMockScannedRepos([
VariantAnalysisRepoStatus.Pending,
])
),
};
const repoLabel1 = buildRepoLabel(variantAnalysisHistoryItem1);
expect(repoLabel1).to.equal('0/1 repository');
});
it('should return label when `totalScannedRepositoryCount` is greater than 1', () => {
const repoLabel = buildRepoLabel(variantAnalysisHistoryItem);
expect(repoLabel).to.equal('2/4 repositories');
});
});
});
});

View File

@@ -0,0 +1,20 @@
import { expect } from 'chai';
import { pluralize } from '../../src/pure/word';
describe('word helpers', () => {
describe('pluralize', () => {
it('should return the plural form if the number is 0', () => {
expect(pluralize(0, 'thing', 'things')).to.eq('0 things');
});
it('should return the singular form if the number is 1', () => {
expect(pluralize(1, 'thing', 'things')).to.eq('1 thing');
});
it('should return the plural form if the number is greater than 1', () => {
expect(pluralize(7, 'thing', 'things')).to.eq('7 things');
});
it('should return the empty string if the number is undefined', () => {
expect(pluralize(undefined, 'thing', 'things')).to.eq('');
});
});
});