1- import { pathExists as fs_pathExists , stat , readFile } from "fs-extra" ;
2- import { QuickPickItem , window } from "vscode" ;
3- import { extLogger } from "../common" ;
4- import {
5- getRemoteRepositoryLists ,
6- getRemoteRepositoryListsPath ,
7- isVariantAnalysisReposPanelEnabled ,
8- } from "../config" ;
9- import { OWNER_REGEX , REPO_REGEX } from "../pure/helpers-pure" ;
101import { UserCancellationException } from "../commandRunner" ;
112import { DbManager } from "../databases/db-manager" ;
123import { DbItemKind } from "../databases/db-item" ;
@@ -17,120 +8,42 @@ export interface RepositorySelection {
178 owners ?: string [ ] ;
189}
1910
20- interface RepoListQuickPickItem extends QuickPickItem {
21- repositories ?: string [ ] ;
22- repositoryList ?: string ;
23- useCustomRepo ?: boolean ;
24- useAllReposOfOwner ?: boolean ;
25- }
26-
27- interface RepoList {
28- label : string ;
29- repositories : string [ ] ;
30- }
31-
3211/**
3312 * Gets the repositories or repository lists to run the query against.
3413 * @returns The user selection.
3514 */
3615export async function getRepositorySelection (
3716 dbManager ?: DbManager ,
3817) : Promise < RepositorySelection > {
39- if ( isVariantAnalysisReposPanelEnabled ( ) ) {
40- const selectedDbItem = dbManager ?. getSelectedDbItem ( ) ;
41- if ( selectedDbItem ) {
42- switch ( selectedDbItem . kind ) {
43- case DbItemKind . LocalDatabase || DbItemKind . LocalList :
18+ const selectedDbItem = dbManager ?. getSelectedDbItem ( ) ;
19+ if ( selectedDbItem ) {
20+ switch ( selectedDbItem . kind ) {
21+ case DbItemKind . LocalDatabase || DbItemKind . LocalList :
22+ throw new UserCancellationException (
23+ "Local databases and lists are not supported yet." ,
24+ ) ;
25+ case DbItemKind . RemoteSystemDefinedList :
26+ return { repositoryLists : [ selectedDbItem . listName ] } ;
27+ case DbItemKind . RemoteUserDefinedList :
28+ if ( selectedDbItem . repos . length === 0 ) {
4429 throw new UserCancellationException (
45- "Local databases and lists are not supported yet ." ,
30+ "The selected repository list is empty. Please add repositories to it before running a variant analysis ." ,
4631 ) ;
47- case DbItemKind . RemoteSystemDefinedList :
48- return { repositoryLists : [ selectedDbItem . listName ] } ;
49- case DbItemKind . RemoteUserDefinedList :
50- if ( selectedDbItem . repos . length === 0 ) {
51- throw new UserCancellationException (
52- "The selected repository list is empty. Please add repositories to it before running a variant analysis." ,
53- ) ;
54- } else {
55- return {
56- repositories : selectedDbItem . repos . map (
57- ( repo ) => repo . repoFullName ,
58- ) ,
59- } ;
60- }
61- case DbItemKind . RemoteOwner :
62- return { owners : [ selectedDbItem . ownerName ] } ;
63- case DbItemKind . RemoteRepo :
64- return { repositories : [ selectedDbItem . repoFullName ] } ;
65- }
66- } else {
67- throw new UserCancellationException (
68- "Please select a remote database to run the query against." ,
69- ) ;
32+ } else {
33+ return {
34+ repositories : selectedDbItem . repos . map ( ( repo ) => repo . repoFullName ) ,
35+ } ;
36+ }
37+ case DbItemKind . RemoteOwner :
38+ return { owners : [ selectedDbItem . ownerName ] } ;
39+ case DbItemKind . RemoteRepo :
40+ return { repositories : [ selectedDbItem . repoFullName ] } ;
7041 }
7142 }
7243
73- const quickPickItems = [
74- createCustomRepoQuickPickItem ( ) ,
75- createAllReposOfOwnerQuickPickItem ( ) ,
76- ...createSystemDefinedRepoListsQuickPickItems ( ) ,
77- ...( await createUserDefinedRepoListsQuickPickItems ( ) ) ,
78- ] ;
79-
80- const options = {
81- placeHolder :
82- "Select a repository list. You can define repository lists in the `codeQL.variantAnalysis.repositoryLists` setting." ,
83- ignoreFocusOut : true ,
84- } ;
85-
86- const quickpick = await window . showQuickPick < RepoListQuickPickItem > (
87- quickPickItems ,
88- options ,
44+ throw new UserCancellationException (
45+ "Please select a remote database to run the query against." ,
8946 ) ;
90-
91- if ( ! quickpick ) {
92- // We don't need to display a warning pop-up in this case, since the user just escaped out of the operation.
93- // We set 'true' to make this a silent exception.
94- throw new UserCancellationException ( "No repositories selected" , true ) ;
95- }
96-
97- if ( quickpick . repositories ?. length ) {
98- void extLogger . log (
99- `Selected repositories: ${ quickpick . repositories . join ( ", " ) } ` ,
100- ) ;
101- return { repositories : quickpick . repositories } ;
102- } else if ( quickpick . repositoryList ) {
103- void extLogger . log ( `Selected repository list: ${ quickpick . repositoryList } ` ) ;
104- return { repositoryLists : [ quickpick . repositoryList ] } ;
105- } else if ( quickpick . useCustomRepo ) {
106- const customRepo = await getCustomRepo ( ) ;
107- if ( customRepo === undefined ) {
108- // The user cancelled, do nothing.
109- throw new UserCancellationException ( "No repositories selected" , true ) ;
110- }
111- if ( ! customRepo || ! REPO_REGEX . test ( customRepo ) ) {
112- throw new UserCancellationException (
113- "Invalid repository format. Please enter a valid repository in the format <owner>/<repo> (e.g. github/codeql)" ,
114- ) ;
115- }
116- void extLogger . log ( `Entered repository: ${ customRepo } ` ) ;
117- return { repositories : [ customRepo ] } ;
118- } else if ( quickpick . useAllReposOfOwner ) {
119- const owner = await getOwner ( ) ;
120- if ( owner === undefined ) {
121- // The user cancelled, do nothing.
122- throw new UserCancellationException ( "No repositories selected" , true ) ;
123- }
124- if ( ! owner || ! OWNER_REGEX . test ( owner ) ) {
125- throw new Error ( `Invalid user or organization: ${ owner } ` ) ;
126- }
127- void extLogger . log ( `Entered owner: ${ owner } ` ) ;
128- return { owners : [ owner ] } ;
129- } else {
130- // This means the user has selected something, but there is nothing actually linked to this item. We want to show
131- // this to the user.
132- throw new UserCancellationException ( "No repositories selected" , false ) ;
133- }
13447}
13548
13649/**
@@ -147,133 +60,3 @@ export function isValidSelection(repoSelection: RepositorySelection): boolean {
14760 repositories . length > 0 || repositoryLists . length > 0 || owners . length > 0
14861 ) ;
14962}
150-
151- function createSystemDefinedRepoListsQuickPickItems ( ) : RepoListQuickPickItem [ ] {
152- const topNs = [ 10 , 100 , 1000 ] ;
153-
154- return topNs . map (
155- ( n ) =>
156- ( {
157- label : `$(star) Top ${ n } ` ,
158- repositoryList : `top_${ n } ` ,
159- alwaysShow : true ,
160- } as RepoListQuickPickItem ) ,
161- ) ;
162- }
163-
164- async function readExternalRepoLists ( ) : Promise < RepoList [ ] > {
165- const repoLists : RepoList [ ] = [ ] ;
166-
167- const path = getRemoteRepositoryListsPath ( ) ;
168- if ( ! path ) {
169- return repoLists ;
170- }
171-
172- await validateExternalRepoListsFile ( path ) ;
173- const json = await readExternalRepoListsJson ( path ) ;
174-
175- for ( const [ repoListName , repositories ] of Object . entries ( json ) ) {
176- if ( ! Array . isArray ( repositories ) ) {
177- throw Error (
178- "Invalid repository lists file. It should contain an array of repositories for each list." ,
179- ) ;
180- }
181-
182- repoLists . push ( {
183- label : repoListName ,
184- repositories,
185- } ) ;
186- }
187-
188- return repoLists ;
189- }
190-
191- async function validateExternalRepoListsFile ( path : string ) : Promise < void > {
192- const pathExists = await fs_pathExists ( path ) ;
193- if ( ! pathExists ) {
194- throw Error ( `External repository lists file does not exist at ${ path } ` ) ;
195- }
196-
197- const pathStat = await stat ( path ) ;
198- if ( pathStat . isDirectory ( ) ) {
199- throw Error (
200- "External repository lists path should not point to a directory" ,
201- ) ;
202- }
203- }
204-
205- async function readExternalRepoListsJson (
206- path : string ,
207- ) : Promise < Record < string , unknown > > {
208- let json ;
209-
210- try {
211- const fileContents = await readFile ( path , "utf8" ) ;
212- json = await JSON . parse ( fileContents ) ;
213- } catch ( error ) {
214- throw Error ( "Invalid repository lists file. It should contain valid JSON." ) ;
215- }
216-
217- if ( Array . isArray ( json ) ) {
218- throw Error (
219- "Invalid repository lists file. It should be an object mapping names to a list of repositories." ,
220- ) ;
221- }
222-
223- return json ;
224- }
225-
226- function readRepoListsFromSettings ( ) : RepoList [ ] {
227- const repoLists = getRemoteRepositoryLists ( ) ;
228- if ( ! repoLists ) {
229- return [ ] ;
230- }
231-
232- return Object . entries ( repoLists ) . map < RepoList > ( ( [ label , repositories ] ) => ( {
233- label,
234- repositories,
235- } ) ) ;
236- }
237-
238- async function createUserDefinedRepoListsQuickPickItems ( ) : Promise <
239- RepoListQuickPickItem [ ]
240- > {
241- const repoListsFromSetings = readRepoListsFromSettings ( ) ;
242- const repoListsFromExternalFile = await readExternalRepoLists ( ) ;
243-
244- return [ ...repoListsFromSetings , ...repoListsFromExternalFile ] ;
245- }
246-
247- function createCustomRepoQuickPickItem ( ) : RepoListQuickPickItem {
248- return {
249- label : "$(edit) Enter a GitHub repository" ,
250- useCustomRepo : true ,
251- alwaysShow : true ,
252- } ;
253- }
254-
255- function createAllReposOfOwnerQuickPickItem ( ) : RepoListQuickPickItem {
256- return {
257- label : "$(edit) Enter a GitHub user or organization" ,
258- useAllReposOfOwner : true ,
259- alwaysShow : true ,
260- } ;
261- }
262-
263- async function getCustomRepo ( ) : Promise < string | undefined > {
264- return await window . showInputBox ( {
265- title :
266- "Enter a GitHub repository in the format <owner>/<repo> (e.g. github/codeql)" ,
267- placeHolder : "<owner>/<repo>" ,
268- prompt :
269- "Tip: you can save frequently used repositories in the `codeQL.variantAnalysis.repositoryLists` setting" ,
270- ignoreFocusOut : true ,
271- } ) ;
272- }
273-
274- async function getOwner ( ) : Promise < string | undefined > {
275- return await window . showInputBox ( {
276- title : "Enter a GitHub user or organization" ,
277- ignoreFocusOut : true ,
278- } ) ;
279- }
0 commit comments