Skip to content

Commit 5838f1b

Browse files
authored
Merge pull request #1765 from github/koesie10/selected-copy
Use selected repositories for copying repo lists
2 parents d7fd84c + bbaa27a commit 5838f1b

File tree

7 files changed

+183
-17
lines changed

7 files changed

+183
-17
lines changed

extensions/ql-vscode/src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
123123
import { VariantAnalysisResultsManager } from './remote-queries/variant-analysis-results-manager';
124124
import { initializeDbModule } from './databases/db-module';
125125
import { ExtensionApp } from './common/vscode/vscode-app';
126-
import { RepositoriesFilterSortState } from './pure/variant-analysis-filter-sort';
126+
import { RepositoriesFilterSortStateWithIds } from './pure/variant-analysis-filter-sort';
127127

128128
/**
129129
* extension.ts
@@ -963,7 +963,7 @@ async function activateWithInstalledDistribution(
963963
);
964964

965965
ctx.subscriptions.push(
966-
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortState) => {
966+
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortStateWithIds) => {
967967
await variantAnalysisManager.copyRepoListToClipboard(variantAnalysisId, filterSort);
968968
})
969969
);

extensions/ql-vscode/src/pure/interface-types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
VariantAnalysisScannedRepositoryResult,
88
VariantAnalysisScannedRepositoryState,
99
} from '../remote-queries/shared/variant-analysis';
10-
import { RepositoriesFilterSortState } from './variant-analysis-filter-sort';
10+
import { RepositoriesFilterSortStateWithIds } from './variant-analysis-filter-sort';
1111

1212
/**
1313
* This module contains types and code that are shared between
@@ -475,7 +475,7 @@ export interface OpenQueryTextMessage {
475475

476476
export interface CopyRepositoryListMessage {
477477
t: 'copyRepositoryList';
478-
filterSort?: RepositoriesFilterSortState;
478+
filterSort?: RepositoriesFilterSortStateWithIds;
479479
}
480480

481481
export interface ExportResultsMessage {

extensions/ql-vscode/src/pure/variant-analysis-filter-sort.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export type RepositoriesFilterSortState = {
1313
sortKey: SortKey;
1414
}
1515

16+
export type RepositoriesFilterSortStateWithIds = RepositoriesFilterSortState & {
17+
repositoryIds?: number[];
18+
}
19+
1620
export const defaultFilterSortState: RepositoriesFilterSortState = {
1721
searchValue: '',
1822
sortKey: SortKey.Name,
@@ -52,7 +56,7 @@ export function compareRepository(filterSortState: RepositoriesFilterSortState |
5256
}
5357

5458
type SortableResult = {
55-
repository: SortableRepository;
59+
repository: SortableRepository & Pick<Repository, 'id'>;
5660
resultCount?: number;
5761
}
5862

@@ -72,11 +76,7 @@ export function compareWithResults(filterSortState: RepositoriesFilterSortState
7276
};
7377
}
7478

75-
// These define the behavior for undefined input values
76-
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[], filterSortState: RepositoriesFilterSortState | undefined): T[];
77-
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined;
78-
79-
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined {
79+
export function filterAndSortRepositoriesWithResultsByName<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined {
8080
if (!repositories) {
8181
return undefined;
8282
}
@@ -85,3 +85,17 @@ export function filterAndSortRepositoriesWithResults<T extends SortableResult>(r
8585
.filter(repo => matchesFilter(repo.repository, filterSortState))
8686
.sort(compareWithResults(filterSortState));
8787
}
88+
89+
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortStateWithIds | undefined): T[] | undefined {
90+
if (!repositories) {
91+
return undefined;
92+
}
93+
94+
if (filterSortState?.repositoryIds && filterSortState.repositoryIds.length > 0) {
95+
return repositories
96+
.filter(repo => filterSortState.repositoryIds?.includes(repo.repository.id))
97+
.sort(compareWithResults(filterSortState));
98+
}
99+
100+
return filterAndSortRepositoriesWithResultsByName(repositories, filterSortState);
101+
}

extensions/ql-vscode/src/remote-queries/variant-analysis-manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { CodeQLCliServer } from '../cli';
3333
import {
3434
defaultFilterSortState,
3535
filterAndSortRepositoriesWithResults,
36-
RepositoriesFilterSortState,
36+
RepositoriesFilterSortStateWithIds,
3737
} from '../pure/variant-analysis-filter-sort';
3838

3939
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
@@ -371,7 +371,7 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
371371
await cancelVariantAnalysis(credentials, variantAnalysis);
372372
}
373373

374-
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortState = defaultFilterSortState) {
374+
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortStateWithIds = defaultFilterSortState) {
375375
const variantAnalysis = this.variantAnalyses.get(variantAnalysisId);
376376
if (!variantAnalysis) {
377377
throw new Error(`No variant analysis with id: ${variantAnalysisId}`);

extensions/ql-vscode/src/view/variant-analysis/VariantAnalysis.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,12 @@ export function VariantAnalysis({
9797
const copyRepositoryList = useCallback(() => {
9898
vscode.postMessage({
9999
t: 'copyRepositoryList',
100-
filterSort: filterSortState,
100+
filterSort: {
101+
...filterSortState,
102+
repositoryIds: selectedRepositoryIds,
103+
},
101104
});
102-
}, [filterSortState]);
105+
}, [filterSortState, selectedRepositoryIds]);
103106

104107
if (variantAnalysis?.actionsWorkflowRunId === undefined) {
105108
return <VariantAnalysisLoading />;

extensions/ql-vscode/src/view/variant-analysis/VariantAnalysisAnalyzedRepos.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
VariantAnalysisScannedRepositoryState
99
} from '../../remote-queries/shared/variant-analysis';
1010
import {
11-
filterAndSortRepositoriesWithResults,
11+
filterAndSortRepositoriesWithResultsByName,
1212
RepositoriesFilterSortState,
1313
} from '../../pure/variant-analysis-filter-sort';
1414

@@ -55,7 +55,7 @@ export const VariantAnalysisAnalyzedRepos = ({
5555
}, [repositoryResults]);
5656

5757
const repositories = useMemo(() => {
58-
return filterAndSortRepositoriesWithResults(variantAnalysis.scannedRepos, filterSortState);
58+
return filterAndSortRepositoriesWithResultsByName(variantAnalysis.scannedRepos, filterSortState);
5959
}, [filterSortState, variantAnalysis.scannedRepos]);
6060

6161
const onSelectedChange = useCallback((repositoryId: number, selected: boolean) => {

extensions/ql-vscode/src/view/variant-analysis/__tests__/filterSort.spec.ts

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { compareRepository, compareWithResults, defaultFilterSortState, matchesFilter, SortKey } from '../../../pure/variant-analysis-filter-sort';
1+
import {
2+
compareRepository,
3+
compareWithResults,
4+
defaultFilterSortState,
5+
filterAndSortRepositoriesWithResults,
6+
filterAndSortRepositoriesWithResultsByName,
7+
matchesFilter,
8+
SortKey,
9+
} from '../../../pure/variant-analysis-filter-sort';
210

311
// TODO: Move this file to the "pure" tests once it has been switched to Jest
412
describe(matchesFilter.name, () => {
@@ -170,11 +178,13 @@ describe(compareWithResults.name, () => {
170178

171179
const left = {
172180
repository: {
181+
id: 10,
173182
fullName: 'github/galaxy',
174183
},
175184
};
176185
const right = {
177186
repository: {
187+
id: 12,
178188
fullName: 'github/world',
179189
},
180190
};
@@ -192,12 +202,14 @@ describe(compareWithResults.name, () => {
192202

193203
const left = {
194204
repository: {
205+
id: 11,
195206
fullName: 'github/galaxy',
196207
stargazersCount: 1,
197208
},
198209
};
199210
const right = {
200211
repository: {
212+
id: 12,
201213
fullName: 'github/world',
202214
stargazersCount: 10,
203215
},
@@ -216,12 +228,14 @@ describe(compareWithResults.name, () => {
216228

217229
const left = {
218230
repository: {
231+
id: 11,
219232
fullName: 'github/galaxy',
220233
updatedAt: '2020-01-01T00:00:00Z',
221234
},
222235
};
223236
const right = {
224237
repository: {
238+
id: 12,
225239
fullName: 'github/world',
226240
updatedAt: '2021-01-01T00:00:00Z',
227241
},
@@ -240,12 +254,14 @@ describe(compareWithResults.name, () => {
240254

241255
const left = {
242256
repository: {
257+
id: 11,
243258
fullName: 'github/galaxy',
244259
},
245260
resultCount: 10,
246261
};
247262
const right = {
248263
repository: {
264+
id: 12,
249265
fullName: 'github/world',
250266
},
251267
resultCount: 100,
@@ -278,3 +294,136 @@ describe(compareWithResults.name, () => {
278294
});
279295
});
280296
});
297+
298+
describe(filterAndSortRepositoriesWithResultsByName.name, () => {
299+
const repositories = [
300+
{
301+
repository: {
302+
id: 10,
303+
fullName: 'github/galaxy',
304+
},
305+
resultCount: 10,
306+
},
307+
{
308+
repository: {
309+
id: 11,
310+
fullName: 'github/world',
311+
},
312+
resultCount: undefined,
313+
},
314+
{
315+
repository: {
316+
id: 13,
317+
fullName: 'github/planet',
318+
},
319+
resultCount: 500,
320+
},
321+
{
322+
repository: {
323+
id: 783532,
324+
fullName: 'github/stars',
325+
},
326+
resultCount: 8000,
327+
}
328+
];
329+
330+
describe('when sort key is given without filter', () => {
331+
it('returns the correct results', () => {
332+
expect(filterAndSortRepositoriesWithResultsByName(repositories, {
333+
...defaultFilterSortState,
334+
sortKey: SortKey.ResultsCount,
335+
})).toEqual([repositories[3], repositories[2], repositories[0], repositories[1]]);
336+
});
337+
});
338+
339+
describe('when sort key and search filter are given', () => {
340+
it('returns the correct results', () => {
341+
expect(filterAndSortRepositoriesWithResultsByName(repositories, {
342+
...defaultFilterSortState,
343+
sortKey: SortKey.ResultsCount,
344+
searchValue: 'la',
345+
})).toEqual([repositories[2], repositories[0]]);
346+
});
347+
});
348+
});
349+
350+
describe(filterAndSortRepositoriesWithResults.name, () => {
351+
const repositories = [
352+
{
353+
repository: {
354+
id: 10,
355+
fullName: 'github/galaxy',
356+
},
357+
resultCount: 10,
358+
},
359+
{
360+
repository: {
361+
id: 11,
362+
fullName: 'github/world',
363+
},
364+
resultCount: undefined,
365+
},
366+
{
367+
repository: {
368+
id: 13,
369+
fullName: 'github/planet',
370+
},
371+
resultCount: 500,
372+
},
373+
{
374+
repository: {
375+
id: 783532,
376+
fullName: 'github/stars',
377+
},
378+
resultCount: 8000,
379+
}
380+
];
381+
382+
describe('when sort key is given without filter', () => {
383+
it('returns the correct results', () => {
384+
expect(filterAndSortRepositoriesWithResults(repositories, {
385+
...defaultFilterSortState,
386+
sortKey: SortKey.ResultsCount,
387+
})).toEqual([repositories[3], repositories[2], repositories[0], repositories[1]]);
388+
});
389+
});
390+
391+
describe('when sort key and search filter are given', () => {
392+
it('returns the correct results', () => {
393+
expect(filterAndSortRepositoriesWithResults(repositories, {
394+
...defaultFilterSortState,
395+
sortKey: SortKey.ResultsCount,
396+
searchValue: 'la',
397+
})).toEqual([repositories[2], repositories[0]]);
398+
});
399+
});
400+
401+
describe('when sort key, search filter, and repository ids are given', () => {
402+
it('returns the correct results', () => {
403+
expect(filterAndSortRepositoriesWithResults(repositories, {
404+
...defaultFilterSortState,
405+
sortKey: SortKey.ResultsCount,
406+
searchValue: 'la',
407+
repositoryIds: [repositories[1].repository.id, repositories[3].repository.id],
408+
})).toEqual([repositories[3], repositories[1]]);
409+
});
410+
});
411+
412+
describe('when repository ids are given', () => {
413+
it('returns the correct results', () => {
414+
expect(filterAndSortRepositoriesWithResults(repositories, {
415+
...defaultFilterSortState,
416+
repositoryIds: [repositories[0].repository.id, repositories[3].repository.id],
417+
})).toEqual([repositories[0], repositories[3]]);
418+
});
419+
});
420+
421+
describe('when empty repository ids are given', () => {
422+
it('returns the correct results', () => {
423+
expect(filterAndSortRepositoriesWithResults(repositories, {
424+
...defaultFilterSortState,
425+
repositoryIds: [],
426+
})).toEqual([repositories[0], repositories[2], repositories[3], repositories[1]]);
427+
});
428+
});
429+
});

0 commit comments

Comments
 (0)