1- import { TreeView , TreeViewExpansionEvent , window , workspace } from "vscode" ;
2- import { commandRunner } from "../../commandRunner" ;
1+ import {
2+ QuickPickItem ,
3+ TreeView ,
4+ TreeViewExpansionEvent ,
5+ window ,
6+ workspace ,
7+ } from "vscode" ;
8+ import { commandRunner , UserCancellationException } from "../../commandRunner" ;
9+ import {
10+ getNwoFromGitHubUrl ,
11+ isValidGitHubNwo ,
12+ getOwnerFromGitHubUrl ,
13+ isValidGitHubOwner ,
14+ } from "../../common/github-url-identifier-helper" ;
315import { DisposableObject } from "../../pure/disposable-object" ;
416import { DbItem , DbItemKind } from "../db-item" ;
517import { DbManager } from "../db-manager" ;
618import { DbTreeDataProvider } from "./db-tree-data-provider" ;
719import { DbTreeViewItem } from "./db-tree-view-item" ;
820
21+ interface RemoteDatabaseQuickPickItem extends QuickPickItem {
22+ kind : string ;
23+ }
24+
925export class DbPanel extends DisposableObject {
1026 private readonly dataProvider : DbTreeDataProvider ;
1127 private readonly treeView : TreeView < DbTreeViewItem > ;
@@ -40,6 +56,11 @@ export class DbPanel extends DisposableObject {
4056 this . openConfigFile ( ) ,
4157 ) ,
4258 ) ;
59+ this . push (
60+ commandRunner ( "codeQLDatabasesExperimental.addNewDatabase" , ( ) =>
61+ this . addNewRemoteDatabase ( ) ,
62+ ) ,
63+ ) ;
4364 this . push (
4465 commandRunner ( "codeQLDatabasesExperimental.addNewList" , ( ) =>
4566 this . addNewRemoteList ( ) ,
@@ -59,6 +80,77 @@ export class DbPanel extends DisposableObject {
5980 await window . showTextDocument ( document ) ;
6081 }
6182
83+ private async addNewRemoteDatabase ( ) : Promise < void > {
84+ const quickPickItems = [
85+ {
86+ label : "$(repo) From a GitHub repository" ,
87+ detail : "Add a remote repository from GitHub" ,
88+ alwaysShow : true ,
89+ kind : "repo" ,
90+ } ,
91+ {
92+ label : "$(organization) All repositories of a GitHub org or owner" ,
93+ detail :
94+ "Add a remote list of repositories from a GitHub organization/owner" ,
95+ alwaysShow : true ,
96+ kind : "owner" ,
97+ } ,
98+ ] ;
99+ const databaseKind =
100+ await window . showQuickPick < RemoteDatabaseQuickPickItem > ( quickPickItems , {
101+ title : "Add a remote repository" ,
102+ placeHolder : "Select an option" ,
103+ ignoreFocusOut : true ,
104+ } ) ;
105+ if ( ! databaseKind ) {
106+ // We don't need to display a warning pop-up in this case, since the user just escaped out of the operation.
107+ // We set 'true' to make this a silent exception.
108+ throw new UserCancellationException ( "No repository selected" , true ) ;
109+ }
110+ if ( databaseKind . kind === "repo" ) {
111+ await this . addNewRemoteRepo ( ) ;
112+ } else if ( databaseKind . kind === "owner" ) {
113+ await this . addNewRemoteOwner ( ) ;
114+ }
115+ }
116+
117+ private async addNewRemoteRepo ( ) : Promise < void > {
118+ const repoName = await window . showInputBox ( {
119+ title : "Add a remote repository" ,
120+ prompt : "Insert a GitHub repository URL or name with owner" ,
121+ placeHolder : "github.com/<owner>/<repo> or <owner>/<repo>" ,
122+ } ) ;
123+ if ( ! repoName ) {
124+ return ;
125+ }
126+
127+ const nwo = getNwoFromGitHubUrl ( repoName ) || repoName ;
128+ if ( ! isValidGitHubNwo ( nwo ) ) {
129+ throw new Error ( `Invalid GitHub repository: ${ repoName } ` ) ;
130+ }
131+
132+ await this . dbManager . addNewRemoteRepo ( nwo ) ;
133+ }
134+
135+ private async addNewRemoteOwner ( ) : Promise < void > {
136+ const ownerName = await window . showInputBox ( {
137+ title : "Add all repositories of a GitHub org or owner" ,
138+ prompt : "Insert a GitHub organization or owner name" ,
139+ placeHolder : "github.com/<owner> or <owner>" ,
140+ } ) ;
141+
142+ if ( ! ownerName ) {
143+ return ;
144+ }
145+
146+ const owner = getOwnerFromGitHubUrl ( ownerName ) || ownerName ;
147+ if ( ! isValidGitHubOwner ( owner ) ) {
148+ throw new Error ( `Invalid user or organization: ${ owner } ` ) ;
149+ }
150+
151+ await this . dbManager . addNewRemoteOwner ( owner ) ;
152+ }
153+
62154 private async addNewRemoteList ( ) : Promise < void > {
63155 const listName = await window . showInputBox ( {
64156 prompt : "Enter a name for the new list" ,
0 commit comments