11import type { Database } from 'bun:sqlite'
2- import type { GitCredential , Repo } from '@opencode-manager/shared'
2+ import type { GitCredential , Repo , UserPreferences } from '@opencode-manager/shared'
33import { SettingsService } from './settings'
44import {
55 findPatCredentialForHost ,
66 getSSHCredentialsForHost ,
77 createGitEnv ,
8+ createGhCliEnv ,
89 findGitHubCredential ,
910 type ResolvedGitCredential ,
1011} from '../utils/git-auth'
@@ -22,6 +23,12 @@ interface CredentialResolutionOptions {
2223 repoId ?: number
2324}
2425
26+ interface CredentialResolutionContext {
27+ preferences : UserPreferences
28+ credentials : GitCredential [ ]
29+ repo : Repo | null
30+ }
31+
2532export class CredentialProvider {
2633 private settingsService : SettingsService
2734 private database : Database
@@ -32,8 +39,7 @@ export class CredentialProvider {
3239 }
3340
3441 getGitCredentials ( ) : GitCredential [ ] {
35- const settings = this . settingsService . getSettings ( 'default' )
36- return ( settings . preferences . gitCredentials || [ ] ) as GitCredential [ ]
42+ return this . getCredentials ( this . getPreferences ( ) )
3743 }
3844
3945 getGitCredentialById ( credentialId : string | undefined ) : GitCredential | null {
@@ -42,10 +48,10 @@ export class CredentialProvider {
4248 }
4349
4450 getPatCredentialForHost ( hostname : string , options : CredentialResolutionOptions = { } ) : ResolvedGitCredential | null {
45- const credentials = this . getGitCredentials ( )
46- const selectedCredential = this . getSelectedCredential ( options , credentials )
51+ const context = this . resolveContext ( options )
52+ const selectedCredential = this . getSelectedCredential ( context )
4753 const selectedMatch = selectedCredential ? findPatCredentialForHost ( [ selectedCredential ] , hostname ) : null
48- return selectedMatch ?? findPatCredentialForHost ( credentials , hostname )
54+ return selectedMatch ?? findPatCredentialForHost ( context . credentials , hostname )
4955 }
5056
5157 getSshCredentialsForHost ( host : string ) : GitCredential [ ] {
@@ -57,24 +63,22 @@ export class CredentialProvider {
5763 }
5864
5965 getGitEnv ( options : CredentialResolutionOptions = { } ) : Record < string , string > {
60- const credentials = this . getGitCredentials ( )
61- return createGitEnv ( credentials , this . getSelectedCredential ( options , credentials ) )
66+ return this . getGitEnvForContext ( this . resolveContext ( options ) )
6267 }
6368
6469 isSandboxGitCredentialsAllowed ( options : CredentialResolutionOptions = { } ) : boolean {
65- const repo = this . resolveRepo ( options )
66- if ( repo ) {
67- const repoOverride = getRepoSandboxGitCredentials ( this . database , repo . id )
68- if ( repoOverride !== null ) return repoOverride
69- }
70-
71- return this . settingsService . getSettings ( 'default' ) . preferences . sandbox ?. gitCredentials === true
70+ return this . getSandboxGitCredentialsAllowed ( options )
7271 }
7372
7473 getSandboxGitEnv ( options : CredentialResolutionOptions = { } ) : Record < string , string > {
75- if ( ! this . isSandboxGitCredentialsAllowed ( options ) ) return { }
74+ const repo = this . resolveRepo ( options )
75+ const repoOverride = repo ? getRepoSandboxGitCredentials ( this . database , repo . id ) : null
76+ if ( repoOverride === false ) return { }
77+
78+ const context = this . resolveContext ( options , repo )
79+ if ( repoOverride !== true && context . preferences . sandbox ?. gitCredentials !== true ) return { }
7680
77- const gitEnv = this . getGitEnv ( options )
81+ const gitEnv = this . getGitEnvForContext ( context )
7882 if ( gitEnv . GIT_CONFIG_COUNT === '0' ) return { }
7983
8084 const { env, dropped } = limitForwardedGitConfigs ( gitEnv )
@@ -84,7 +88,43 @@ export class CredentialProvider {
8488 )
8589 }
8690
87- return { ...env , ...this . getGhCliEnv ( options ) }
91+ return { ...env , ...this . getGhCliEnvForContext ( context ) }
92+ }
93+
94+ getGhCliEnv ( options : CredentialResolutionOptions = { } ) : Record < string , string > {
95+ return this . getGhCliEnvForContext ( this . resolveContext ( options ) )
96+ }
97+
98+ private resolveContext ( options : CredentialResolutionOptions , repo = this . resolveRepo ( options ) ) : CredentialResolutionContext {
99+ const preferences = this . getPreferences ( )
100+ return {
101+ preferences,
102+ credentials : this . getCredentials ( preferences ) ,
103+ repo,
104+ }
105+ }
106+
107+ private getPreferences ( ) : UserPreferences {
108+ return this . settingsService . getSettings ( 'default' ) . preferences
109+ }
110+
111+ private getCredentials ( preferences : UserPreferences ) : GitCredential [ ] {
112+ return ( preferences . gitCredentials || [ ] ) as GitCredential [ ]
113+ }
114+
115+ private getGitEnvForContext ( context : CredentialResolutionContext ) : Record < string , string > {
116+ return createGitEnv ( context . credentials , this . getSelectedCredential ( context ) )
117+ }
118+
119+ private getGhCliEnvForContext ( context : CredentialResolutionContext ) : Record < string , string > {
120+ const credential = this . getGhCliCredential ( context )
121+ return createGhCliEnv ( credential ? [ credential ] : [ ] )
122+ }
123+
124+ private getSandboxGitCredentialsAllowed ( options : CredentialResolutionOptions ) : boolean {
125+ const repo = this . resolveRepo ( options )
126+ const repoOverride = repo ? getRepoSandboxGitCredentials ( this . database , repo . id ) : null
127+ return repoOverride ?? ( this . getPreferences ( ) . sandbox ?. gitCredentials === true )
88128 }
89129
90130 private resolveRepo ( options : CredentialResolutionOptions ) : Repo | null {
@@ -94,34 +134,25 @@ export class CredentialProvider {
94134 return options . cwd ? getRepoByDirectory ( this . database , options . cwd ) : null
95135 }
96136
97- getGhCliEnv ( options : CredentialResolutionOptions = { } ) : Record < string , string > {
98- const credential = this . getGhCliCredential ( options )
99- if ( ! credential ?. token ) return { }
100- return { GH_TOKEN : credential . token , GITHUB_TOKEN : credential . token }
101- }
102-
103- private getGhCliCredential ( options : CredentialResolutionOptions ) : GitCredential | null {
104- const credentials = this . getGitCredentials ( )
105- const selectedCredential = this . getSelectedCredential ( options , credentials )
137+ private getGhCliCredential ( context : CredentialResolutionContext ) : GitCredential | null {
138+ const selectedCredential = this . getSelectedCredential ( context )
106139 if ( this . isGithubPatCredential ( selectedCredential ) ) return selectedCredential
107140
108- return findGitHubCredential ( credentials )
141+ return findGitHubCredential ( context . credentials )
109142 }
110143
111- private getSelectedCredential ( options : CredentialResolutionOptions , credentials : GitCredential [ ] ) : GitCredential | null {
112- const repoCredential = this . getRepoCredential ( options , credentials )
144+ private getSelectedCredential ( context : CredentialResolutionContext ) : GitCredential | null {
145+ const repoCredential = this . getRepoCredential ( context )
113146 if ( repoCredential ) return repoCredential
114147
115- const settings = this . settingsService . getSettings ( 'default' )
116- return credentials . find ( ( credential ) => credential . id === settings . preferences . defaultGitCredentialId ) ?? null
148+ return context . credentials . find ( ( credential ) => credential . id === context . preferences . defaultGitCredentialId ) ?? null
117149 }
118150
119- private getRepoCredential ( options : CredentialResolutionOptions , credentials : GitCredential [ ] ) : GitCredential | null {
120- const repo = this . resolveRepo ( options )
121- if ( ! repo ) return null
151+ private getRepoCredential ( context : CredentialResolutionContext ) : GitCredential | null {
152+ if ( ! context . repo ) return null
122153
123- const credentialId = getRepoGitCredentialId ( this . database , repo . id )
124- return credentials . find ( ( credential ) => credential . id === credentialId ) ?? null
154+ const credentialId = getRepoGitCredentialId ( this . database , context . repo . id )
155+ return context . credentials . find ( ( credential ) => credential . id === credentialId ) ?? null
125156 }
126157
127158 private isGithubPatCredential ( credential : GitCredential | null ) : credential is GitCredential {
0 commit comments