Use selected repositories for copying repo lists
This will use the selected repositories to limit which repositories are included in the copied repo list. If there are both selected repositories and a search filter (on the full name), the search filter will be ignored and the selected repositories will be used in full.
This commit is contained in:
@@ -116,7 +116,7 @@ import { createVariantAnalysisContentProvider } from './remote-queries/variant-a
|
|||||||
import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
|
import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
|
||||||
import { VariantAnalysisResultsManager } from './remote-queries/variant-analysis-results-manager';
|
import { VariantAnalysisResultsManager } from './remote-queries/variant-analysis-results-manager';
|
||||||
import { initializeDbModule } from './databases/db-module';
|
import { initializeDbModule } from './databases/db-module';
|
||||||
import { RepositoriesFilterSortState } from './pure/variant-analysis-filter-sort';
|
import { RepositoriesFilterSortStateWithIds } from './pure/variant-analysis-filter-sort';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extension.ts
|
* extension.ts
|
||||||
@@ -946,7 +946,7 @@ async function activateWithInstalledDistribution(
|
|||||||
);
|
);
|
||||||
|
|
||||||
ctx.subscriptions.push(
|
ctx.subscriptions.push(
|
||||||
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortState) => {
|
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortStateWithIds) => {
|
||||||
await variantAnalysisManager.copyRepoListToClipboard(variantAnalysisId, filterSort);
|
await variantAnalysisManager.copyRepoListToClipboard(variantAnalysisId, filterSort);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
VariantAnalysisScannedRepositoryResult,
|
VariantAnalysisScannedRepositoryResult,
|
||||||
VariantAnalysisScannedRepositoryState,
|
VariantAnalysisScannedRepositoryState,
|
||||||
} from '../remote-queries/shared/variant-analysis';
|
} from '../remote-queries/shared/variant-analysis';
|
||||||
import { RepositoriesFilterSortState } from './variant-analysis-filter-sort';
|
import { RepositoriesFilterSortStateWithIds } from './variant-analysis-filter-sort';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This module contains types and code that are shared between
|
* This module contains types and code that are shared between
|
||||||
@@ -475,7 +475,7 @@ export interface OpenQueryTextMessage {
|
|||||||
|
|
||||||
export interface CopyRepositoryListMessage {
|
export interface CopyRepositoryListMessage {
|
||||||
t: 'copyRepositoryList';
|
t: 'copyRepositoryList';
|
||||||
filterSort?: RepositoriesFilterSortState;
|
filterSort?: RepositoriesFilterSortStateWithIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenLogsMessage {
|
export interface OpenLogsMessage {
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ export type RepositoriesFilterSortState = {
|
|||||||
sortKey: SortKey;
|
sortKey: SortKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RepositoriesFilterSortStateWithIds = RepositoriesFilterSortState & {
|
||||||
|
repositoryIds?: number[];
|
||||||
|
}
|
||||||
|
|
||||||
export const defaultFilterSortState: RepositoriesFilterSortState = {
|
export const defaultFilterSortState: RepositoriesFilterSortState = {
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
sortKey: SortKey.Name,
|
sortKey: SortKey.Name,
|
||||||
@@ -52,7 +56,7 @@ export function compareRepository(filterSortState: RepositoriesFilterSortState |
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SortableResult = {
|
type SortableResult = {
|
||||||
repository: SortableRepository;
|
repository: SortableRepository & Pick<Repository, 'id'>;
|
||||||
resultCount?: number;
|
resultCount?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,16 +76,30 @@ export function compareWithResults(filterSortState: RepositoriesFilterSortState
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// These define the behavior for undefined input values
|
function hasRepositoryIds(filterSortState: RepositoriesFilterSortState | RepositoriesFilterSortStateWithIds | undefined): filterSortState is RepositoriesFilterSortStateWithIds {
|
||||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[], filterSortState: RepositoriesFilterSortState | undefined): T[];
|
if (!filterSortState) {
|
||||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined {
|
return 'repositoryIds' in filterSortState;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFilterOnRepositoryIds(filterSortState: RepositoriesFilterSortState | RepositoriesFilterSortStateWithIds | undefined): filterSortState is RepositoriesFilterSortStateWithIds & Required<Pick<RepositoriesFilterSortStateWithIds, 'repositoryIds'>> {
|
||||||
|
return hasRepositoryIds(filterSortState) && filterSortState.repositoryIds !== undefined && filterSortState.repositoryIds.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These define the behavior for undefined input values
|
||||||
|
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[], filterSortState: RepositoriesFilterSortState | RepositoriesFilterSortStateWithIds | undefined): T[];
|
||||||
|
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | RepositoriesFilterSortStateWithIds | undefined): T[] | undefined;
|
||||||
|
|
||||||
|
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | RepositoriesFilterSortStateWithIds | undefined): T[] | undefined {
|
||||||
if (!repositories) {
|
if (!repositories) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return repositories
|
const filteredRepositories = isFilterOnRepositoryIds(filterSortState) ?
|
||||||
.filter(repo => matchesFilter(repo.repository, filterSortState))
|
repositories.filter(repo => filterSortState.repositoryIds.includes(repo.repository.id)) :
|
||||||
.sort(compareWithResults(filterSortState));
|
repositories.filter(repo => matchesFilter(repo.repository, filterSortState));
|
||||||
|
|
||||||
|
return filteredRepositories.sort(compareWithResults(filterSortState));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import { CodeQLCliServer } from '../cli';
|
|||||||
import {
|
import {
|
||||||
defaultFilterSortState,
|
defaultFilterSortState,
|
||||||
filterAndSortRepositoriesWithResults,
|
filterAndSortRepositoriesWithResults,
|
||||||
RepositoriesFilterSortState,
|
RepositoriesFilterSortStateWithIds,
|
||||||
} from '../pure/variant-analysis-filter-sort';
|
} from '../pure/variant-analysis-filter-sort';
|
||||||
|
|
||||||
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
|
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
|
||||||
@@ -373,7 +373,7 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
|||||||
await cancelVariantAnalysis(credentials, variantAnalysis);
|
await cancelVariantAnalysis(credentials, variantAnalysis);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortState = defaultFilterSortState) {
|
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortStateWithIds = defaultFilterSortState) {
|
||||||
const variantAnalysis = this.variantAnalyses.get(variantAnalysisId);
|
const variantAnalysis = this.variantAnalyses.get(variantAnalysisId);
|
||||||
if (!variantAnalysis) {
|
if (!variantAnalysis) {
|
||||||
throw new Error(`No variant analysis with id: ${variantAnalysisId}`);
|
throw new Error(`No variant analysis with id: ${variantAnalysisId}`);
|
||||||
|
|||||||
@@ -91,9 +91,12 @@ export function VariantAnalysis({
|
|||||||
const copyRepositoryList = useCallback(() => {
|
const copyRepositoryList = useCallback(() => {
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
t: 'copyRepositoryList',
|
t: 'copyRepositoryList',
|
||||||
filterSort: filterSortState,
|
filterSort: {
|
||||||
|
...filterSortState,
|
||||||
|
repositoryIds: selectedRepositoryIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}, [filterSortState]);
|
}, [filterSortState, selectedRepositoryIds]);
|
||||||
|
|
||||||
if (variantAnalysis?.actionsWorkflowRunId === undefined) {
|
if (variantAnalysis?.actionsWorkflowRunId === undefined) {
|
||||||
return <VariantAnalysisLoading />;
|
return <VariantAnalysisLoading />;
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
import { compareRepository, compareWithResults, defaultFilterSortState, matchesFilter, SortKey } from '../../../pure/variant-analysis-filter-sort';
|
import {
|
||||||
|
compareRepository,
|
||||||
|
compareWithResults,
|
||||||
|
defaultFilterSortState,
|
||||||
|
filterAndSortRepositoriesWithResults,
|
||||||
|
matchesFilter,
|
||||||
|
SortKey,
|
||||||
|
} from '../../../pure/variant-analysis-filter-sort';
|
||||||
|
|
||||||
// TODO: Move this file to the "pure" tests once it has been switched to Jest
|
// TODO: Move this file to the "pure" tests once it has been switched to Jest
|
||||||
describe(matchesFilter.name, () => {
|
describe(matchesFilter.name, () => {
|
||||||
@@ -170,11 +177,13 @@ describe(compareWithResults.name, () => {
|
|||||||
|
|
||||||
const left = {
|
const left = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 10,
|
||||||
fullName: 'github/galaxy',
|
fullName: 'github/galaxy',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const right = {
|
const right = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 12,
|
||||||
fullName: 'github/world',
|
fullName: 'github/world',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -192,12 +201,14 @@ describe(compareWithResults.name, () => {
|
|||||||
|
|
||||||
const left = {
|
const left = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 11,
|
||||||
fullName: 'github/galaxy',
|
fullName: 'github/galaxy',
|
||||||
stargazersCount: 1,
|
stargazersCount: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const right = {
|
const right = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 12,
|
||||||
fullName: 'github/world',
|
fullName: 'github/world',
|
||||||
stargazersCount: 10,
|
stargazersCount: 10,
|
||||||
},
|
},
|
||||||
@@ -216,12 +227,14 @@ describe(compareWithResults.name, () => {
|
|||||||
|
|
||||||
const left = {
|
const left = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 11,
|
||||||
fullName: 'github/galaxy',
|
fullName: 'github/galaxy',
|
||||||
updatedAt: '2020-01-01T00:00:00Z',
|
updatedAt: '2020-01-01T00:00:00Z',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const right = {
|
const right = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 12,
|
||||||
fullName: 'github/world',
|
fullName: 'github/world',
|
||||||
updatedAt: '2021-01-01T00:00:00Z',
|
updatedAt: '2021-01-01T00:00:00Z',
|
||||||
},
|
},
|
||||||
@@ -240,12 +253,14 @@ describe(compareWithResults.name, () => {
|
|||||||
|
|
||||||
const left = {
|
const left = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 11,
|
||||||
fullName: 'github/galaxy',
|
fullName: 'github/galaxy',
|
||||||
},
|
},
|
||||||
resultCount: 10,
|
resultCount: 10,
|
||||||
};
|
};
|
||||||
const right = {
|
const right = {
|
||||||
repository: {
|
repository: {
|
||||||
|
id: 12,
|
||||||
fullName: 'github/world',
|
fullName: 'github/world',
|
||||||
},
|
},
|
||||||
resultCount: 100,
|
resultCount: 100,
|
||||||
@@ -278,3 +293,84 @@ describe(compareWithResults.name, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe(filterAndSortRepositoriesWithResults.name, () => {
|
||||||
|
const repositories = [
|
||||||
|
{
|
||||||
|
repository: {
|
||||||
|
id: 10,
|
||||||
|
fullName: 'github/galaxy',
|
||||||
|
},
|
||||||
|
resultCount: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
repository: {
|
||||||
|
id: 11,
|
||||||
|
fullName: 'github/world',
|
||||||
|
},
|
||||||
|
resultCount: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
repository: {
|
||||||
|
id: 13,
|
||||||
|
fullName: 'github/planet',
|
||||||
|
},
|
||||||
|
resultCount: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
repository: {
|
||||||
|
id: 783532,
|
||||||
|
fullName: 'github/stars',
|
||||||
|
},
|
||||||
|
resultCount: 8000,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('when sort key is given without filter', () => {
|
||||||
|
it('returns the correct results', () => {
|
||||||
|
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||||
|
...defaultFilterSortState,
|
||||||
|
sortKey: SortKey.ResultsCount,
|
||||||
|
})).toEqual([repositories[3], repositories[2], repositories[0], repositories[1]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when sort key and search filter are given', () => {
|
||||||
|
it('returns the correct results', () => {
|
||||||
|
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||||
|
...defaultFilterSortState,
|
||||||
|
sortKey: SortKey.ResultsCount,
|
||||||
|
searchValue: 'la',
|
||||||
|
})).toEqual([repositories[2], repositories[0]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when sort key, search filter, and repository ids are given', () => {
|
||||||
|
it('returns the correct results', () => {
|
||||||
|
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||||
|
...defaultFilterSortState,
|
||||||
|
sortKey: SortKey.ResultsCount,
|
||||||
|
searchValue: 'la',
|
||||||
|
repositoryIds: [repositories[1].repository.id, repositories[3].repository.id],
|
||||||
|
})).toEqual([repositories[3], repositories[1]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when repository ids are given', () => {
|
||||||
|
it('returns the correct results', () => {
|
||||||
|
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||||
|
...defaultFilterSortState,
|
||||||
|
repositoryIds: [repositories[0].repository.id, repositories[3].repository.id],
|
||||||
|
})).toEqual([repositories[0], repositories[3]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when empty repository ids are given', () => {
|
||||||
|
it('returns the correct results', () => {
|
||||||
|
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||||
|
...defaultFilterSortState,
|
||||||
|
repositoryIds: [],
|
||||||
|
})).toEqual([repositories[0], repositories[2], repositories[3], repositories[1]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user