@@ -223,19 +223,9 @@ impl KeychainStorage {
223223 . delete_credential ( )
224224 . map_err ( |e| anyhow:: anyhow!( "keychain probe cleanup failed: {e}" ) ) ?;
225225 }
226- // On Linux, also perform a read probe so we fail fast when the
227- // Secret Service DBus name is unavailable and can fall back to file
228- // storage instead of erroring later during auth flows.
229- #[ cfg( target_os = "linux" ) ]
230- {
231- let entry = keyring:: Entry :: new ( SERVICE_NAME , "__pup_probe__" )
232- . map_err ( |e| anyhow:: anyhow!( "keychain not available: {e}" ) ) ?;
233- linux_keychain_probe_result ( entry. get_password ( ) ) ?;
234- }
235- // On macOS and other non-Windows targets, constructing an Entry is
236- // sufficient to confirm the backend is present; avoid a spurious macOS
237- // authorization dialog.
238- #[ cfg( all( not( target_os = "windows" ) , not( target_os = "linux" ) ) ) ]
226+ // On macOS and Linux, constructing an Entry is sufficient to confirm the
227+ // backend is present; avoid a spurious macOS authorization dialog.
228+ #[ cfg( not( target_os = "windows" ) ) ]
239229 keyring:: Entry :: new ( SERVICE_NAME , "__pup_probe__" )
240230 . map_err ( |e| anyhow:: anyhow!( "keychain not available: {e}" ) ) ?;
241231 Ok ( Self {
@@ -244,16 +234,6 @@ impl KeychainStorage {
244234 }
245235}
246236
247- #[ cfg( all( not( target_arch = "wasm32" ) , target_os = "linux" ) ) ]
248- fn linux_keychain_probe_result (
249- probe_result : std:: result:: Result < String , keyring:: Error > ,
250- ) -> Result < ( ) > {
251- match probe_result {
252- Ok ( _) | Err ( keyring:: Error :: NoEntry ) => Ok ( ( ) ) ,
253- Err ( e) => Err ( anyhow:: anyhow!( "keychain not available: {e}" ) ) ,
254- }
255- }
256-
257237/// Combined per-site state stored in a single keychain entry.
258238/// Consolidating tokens + client credentials into one entry reduces macOS
259239/// authorization dialogs from 2 → 1 per site on first access. KeychainStorage
@@ -722,32 +702,10 @@ fn detect_backend_with(try_keychain: impl Fn() -> Result<KeychainStorage>) -> Bo
722702 match try_keychain ( ) {
723703 Ok ( ks) => Box :: new ( ks) ,
724704 Err ( e) => {
725- // On Linux, the default backend is Secret Service (DBus). If that is
726- // unavailable, fall back to the kernel keyring (keyutils) which does
727- // not require a desktop session or running daemon.
728- #[ cfg( target_os = "linux" ) ]
729- {
730- eprintln ! ( "Warning: Secret Service not available ({e}), trying kernel keyring" ) ;
731- keyring:: set_default_credential_builder (
732- keyring:: keyutils:: default_credential_builder ( ) ,
733- ) ;
734- match try_keychain ( ) {
735- Ok ( ks) => Box :: new ( ks) ,
736- Err ( e2) => {
737- eprintln ! (
738- "Warning: kernel keyring also unavailable ({e2}), using file storage (~/.config/pup/)"
739- ) ;
740- Box :: new ( FileStorage :: new ( ) . expect ( "failed to create file storage" ) )
741- }
742- }
743- }
744- #[ cfg( not( target_os = "linux" ) ) ]
745- {
746- eprintln ! (
747- "Warning: OS keychain not available ({e}), using file storage (~/.config/pup/)"
748- ) ;
749- Box :: new ( FileStorage :: new ( ) . expect ( "failed to create file storage" ) )
750- }
705+ eprintln ! (
706+ "Warning: OS keychain not available ({e}), using file storage (~/.config/pup/)"
707+ ) ;
708+ Box :: new ( FileStorage :: new ( ) . expect ( "failed to create file storage" ) )
751709 }
752710 }
753711}
@@ -1817,35 +1775,8 @@ mod tests {
18171775
18181776 // --- detect_backend ---------------------------------------------------------
18191777
1820- #[ test]
1821- #[ cfg( all( not( target_arch = "wasm32" ) , target_os = "linux" ) ) ]
1822- fn test_linux_keychain_probe_result_accepts_no_entry ( ) {
1823- let result = linux_keychain_probe_result ( Err ( keyring:: Error :: NoEntry ) ) ;
1824- assert ! ( result. is_ok( ) ) ;
1825- }
1826-
1827- #[ test]
1828- #[ cfg( all( not( target_arch = "wasm32" ) , target_os = "linux" ) ) ]
1829- fn test_linux_keychain_probe_result_rejects_platform_failure ( ) {
1830- let err = linux_keychain_probe_result ( Err ( keyring:: Error :: PlatformFailure ( Box :: new (
1831- std:: io:: Error :: new (
1832- std:: io:: ErrorKind :: NotFound ,
1833- "org.freedesktop.DBus.Error.ServiceUnknown" ,
1834- ) ,
1835- ) ) ) )
1836- . unwrap_err ( )
1837- . to_string ( ) ;
1838- assert ! ( err. contains( "keychain not available" ) ) ;
1839- assert ! (
1840- err. contains( "ServiceUnknown" ) ,
1841- "expected dbus service error in message, got: {err}"
1842- ) ;
1843- }
1844-
18451778 // Exercises the FileStorage fallback when the auto-detect keychain probe fails,
18461779 // without requiring OS-level credential-store mocking.
1847- // On Linux this also exercises the kernel-keyring intermediate fallback (which
1848- // also fails because the injected probe always returns Err).
18491780 #[ test]
18501781 #[ cfg( not( target_arch = "wasm32" ) ) ]
18511782 fn test_detect_backend_with_probe_failure_falls_back_to_file ( ) {
@@ -1858,30 +1789,6 @@ mod tests {
18581789 assert_eq ! ( backend. backend_type( ) , BackendType :: File ) ;
18591790 }
18601791
1861- // On Linux, when the Secret Service probe fails but kernel keyring succeeds,
1862- // the backend should be Keychain (keyutils-backed).
1863- #[ test]
1864- #[ cfg( all( not( target_arch = "wasm32" ) , target_os = "linux" ) ) ]
1865- fn test_detect_backend_with_secret_service_failure_falls_back_to_keyutils ( ) {
1866- let _lock = crate :: test_utils:: ENV_LOCK . blocking_lock ( ) ;
1867- let tmp = TempDir :: new ( "detect_keyutils" ) ;
1868- std:: env:: set_var ( "PUP_CONFIG_DIR" , tmp. path ( ) ) ;
1869- std:: env:: remove_var ( "DD_TOKEN_STORAGE" ) ;
1870- let call_count = std:: sync:: atomic:: AtomicU32 :: new ( 0 ) ;
1871- let backend = detect_backend_with ( || {
1872- let n = call_count. fetch_add ( 1 , std:: sync:: atomic:: Ordering :: SeqCst ) ;
1873- if n == 0 {
1874- // First call: simulate Secret Service unavailable
1875- Err ( anyhow:: anyhow!( "secret service unavailable" ) )
1876- } else {
1877- // Second call: keyutils backend probe succeeds
1878- KeychainStorage :: new ( )
1879- }
1880- } ) ;
1881- std:: env:: remove_var ( "PUP_CONFIG_DIR" ) ;
1882- assert_eq ! ( backend. backend_type( ) , BackendType :: Keychain ) ;
1883- }
1884-
18851792 // When DD_TOKEN_STORAGE=keychain is explicitly set but the backend is
18861793 // unavailable, the process panics with a clear message rather than silently
18871794 // falling back (explicit opt-in should fail loudly).
0 commit comments