@@ -170,50 +170,54 @@ export class RepoManager implements IRepoManager {
170
170
// fetch the token here using the connections from the repo. Multiple connections could be referencing this repo, and each
171
171
// may have their own token. This method will just pick the first connection that has a token (if one exists) and uses that. This
172
172
// 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
+ }
179
185
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
+ }
190
195
}
191
- } ) ( ) ;
192
196
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
+ }
198
205
}
199
206
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 ,
208
215
}
209
- break ;
210
216
}
211
217
}
212
218
}
213
219
214
- return password
215
- ? { username, password }
216
- : undefined ;
220
+ return undefined ;
217
221
}
218
222
219
223
private async syncGitRepository ( repo : RepoWithConnections , repoAlreadyInIndexingState : boolean ) {
@@ -244,11 +248,20 @@ export class RepoManager implements IRepoManager {
244
248
} else {
245
249
this . logger . info ( `Cloning ${ repo . displayName } ...` ) ;
246
250
247
- const auth = await this . getAuthForRepo ( repo , this . db ) ;
251
+ const auth = await this . getCloneCredentialsForRepo ( repo , this . db ) ;
248
252
const cloneUrl = new URL ( repo . cloneUrl ) ;
249
253
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
+ }
252
265
}
253
266
254
267
const { durationMs } = await measure ( ( ) => cloneRepository ( cloneUrl . toString ( ) , repoPath , ( { method, stage, progress } ) => {
0 commit comments