@@ -170,50 +170,54 @@ export class RepoManager implements IRepoManager {
170170 // fetch the token here using the connections from the repo. Multiple connections could be referencing this repo, and each
171171 // may have their own token. This method will just pick the first connection that has a token (if one exists) and uses that. This
172172 // may technically cause syncing to fail if that connection's token just so happens to not have access to the repo it's referrencing.
173- private async getAuthForRepo ( repo : RepoWithConnections , db : PrismaClient ) : Promise < { username : string , password : string } | undefined > {
174- const repoConnections = repo . connections ;
175- if ( repoConnections . length === 0 ) {
176- this . logger . error ( `Repo ${ repo . id } has no connections` ) ;
177- return undefined ;
178- }
173+ private async getCloneCredentialsForRepo ( repo : RepoWithConnections , db : PrismaClient ) : Promise < { username ?: string , password : string } | undefined > {
174+
175+ for ( const { connection } of repo . connections ) {
176+ if ( connection . connectionType === 'github' ) {
177+ const config = connection . config as unknown as GithubConnectionConfig ;
178+ if ( config . token ) {
179+ const token = await getTokenFromConfig ( config . token , connection . orgId , db , this . logger ) ;
180+ return {
181+ password : token ,
182+ }
183+ }
184+ }
179185
180- let username = ( ( ) => {
181- switch ( repo . external_codeHostType ) {
182- case 'gitlab' :
183- return 'oauth2' ;
184- case 'bitbucket-cloud' :
185- case 'bitbucket-server' :
186- case 'github' :
187- case 'gitea' :
188- default :
189- return '' ;
186+ else if ( connection . connectionType === 'gitlab' ) {
187+ const config = connection . config as unknown as GitlabConnectionConfig ;
188+ if ( config . token ) {
189+ const token = await getTokenFromConfig ( config . token , connection . orgId , db , this . logger ) ;
190+ return {
191+ username : 'oauth2' ,
192+ password : token ,
193+ }
194+ }
190195 }
191- } ) ( ) ;
192196
193- let password : string | undefined = undefined ;
194- for ( const repoConnection of repoConnections ) {
195- const connection = repoConnection . connection ;
196- if ( connection . connectionType !== 'github' && connection . connectionType !== 'gitlab' && connection . connectionType !== 'gitea' && connection . connectionType !== 'bitbucket' ) {
197- continue ;
197+ else if ( connection . connectionType === 'gitea' ) {
198+ const config = connection . config as unknown as GiteaConnectionConfig ;
199+ if ( config . token ) {
200+ const token = await getTokenFromConfig ( config . token , connection . orgId , db , this . logger ) ;
201+ return {
202+ password : token ,
203+ }
204+ }
198205 }
199206
200- const config = connection . config as unknown as GithubConnectionConfig | GitlabConnectionConfig | GiteaConnectionConfig | BitbucketConnectionConfig ;
201- if ( config . token ) {
202- password = await getTokenFromConfig ( config . token , connection . orgId , db , this . logger ) ;
203- if ( password ) {
204- // If we're using a bitbucket connection we need to set the username to be able to clone the repo
205- if ( connection . connectionType === 'bitbucket' ) {
206- const bitbucketConfig = config as BitbucketConnectionConfig ;
207- username = bitbucketConfig . user ?? "x- token-auth" ;
207+ else if ( connection . connectionType === 'bitbucket' ) {
208+ const config = connection . config as unknown as BitbucketConnectionConfig ;
209+ if ( config . token ) {
210+ const token = await getTokenFromConfig ( config . token , connection . orgId , db , this . logger ) ;
211+ const username = config . user ?? 'x-token-auth' ;
212+ return {
213+ username ,
214+ password : token ,
208215 }
209- break ;
210216 }
211217 }
212218 }
213219
214- return password
215- ? { username, password }
216- : undefined ;
220+ return undefined ;
217221 }
218222
219223 private async syncGitRepository ( repo : RepoWithConnections , repoAlreadyInIndexingState : boolean ) {
@@ -244,11 +248,20 @@ export class RepoManager implements IRepoManager {
244248 } else {
245249 this . logger . info ( `Cloning ${ repo . displayName } ...` ) ;
246250
247- const auth = await this . getAuthForRepo ( repo , this . db ) ;
251+ const auth = await this . getCloneCredentialsForRepo ( repo , this . db ) ;
248252 const cloneUrl = new URL ( repo . cloneUrl ) ;
249253 if ( auth ) {
250- cloneUrl . username = auth . username ;
251- cloneUrl . password = auth . password ;
254+ // @note : URL has a weird behavior where if you set the password but
255+ // _not_ the username, the ":" delimiter will still be present in the
256+ // URL (e.g., https://:password@example.com). To get around this, if
257+ // we only have a password, we set the username to the password.
258+ // @see : https://www.typescriptlang.org/play/?#code/MYewdgzgLgBArgJwDYwLwzAUwO4wKoBKAMgBQBEAFlFAA4QBcA9I5gB4CGAtjUpgHShOZADQBKANwAoREj412ECNhAIAJmhhl5i5WrJTQkELz5IQAcxIy+UEAGUoCAJZhLo0UA
259+ if ( ! auth . username ) {
260+ cloneUrl . username = auth . password ;
261+ } else {
262+ cloneUrl . username = auth . username ;
263+ cloneUrl . password = auth . password ;
264+ }
252265 }
253266
254267 const { durationMs } = await measure ( ( ) => cloneRepository ( cloneUrl . toString ( ) , repoPath , ( { method, stage, progress } ) => {
0 commit comments