From cef1200021cbf1e8767a7b7bfff3068a865fd279 Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Thu, 27 Aug 2026 17:50:01 +0100 Subject: [PATCH 1/2] credstore: allow stores to report their name Allow credential stores to report back their name. This also allows callers who are using the `CredentialStore` facade class to see which backing store was selected. Signed-off-by: Matthew John Cheetham --- src/Core/CredentialCacheStore.cs | 2 ++ src/Core/CredentialStore.cs | 9 +++++++++ src/Core/ICredentialStore.cs | 5 +++++ src/Core/Interop/Linux/SecretServiceCollection.cs | 2 ++ src/Core/Interop/MacOS/MacOSKeychain.cs | 2 ++ src/Core/Interop/Posix/GpgPassCredentialStore.cs | 2 ++ src/Core/Interop/Windows/DpapiCredentialStore.cs | 2 ++ src/Core/Interop/Windows/WindowsCredentialManager.cs | 2 ++ src/Core/NullCredentialStore.cs | 2 ++ src/Core/PlaintextCredentialStore.cs | 2 ++ src/TestInfrastructure/Objects/TestCredentialStore.cs | 2 ++ 11 files changed, 32 insertions(+) diff --git a/src/Core/CredentialCacheStore.cs b/src/Core/CredentialCacheStore.cs index 41d3ffd3c0..7dc534c477 100644 --- a/src/Core/CredentialCacheStore.cs +++ b/src/Core/CredentialCacheStore.cs @@ -23,6 +23,8 @@ public CredentialCacheStore(IGit git, string options) #region ICredentialStore + public string Name => "Git Credential Cache"; + public IList GetAccounts(string service) { // Listing accounts is not supported by the credential-cache store so we just attempt to retrieve diff --git a/src/Core/CredentialStore.cs b/src/Core/CredentialStore.cs index 95d26df320..2ed1061278 100644 --- a/src/Core/CredentialStore.cs +++ b/src/Core/CredentialStore.cs @@ -25,6 +25,15 @@ public CredentialStore(ICommandContext context) #region ICredentialStore + public string Name + { + get + { + EnsureBackingStore(); + return _backingStore.Name; + } + } + public IList GetAccounts(string service) { EnsureBackingStore(); diff --git a/src/Core/ICredentialStore.cs b/src/Core/ICredentialStore.cs index e5c40060e2..aa171b2e3f 100644 --- a/src/Core/ICredentialStore.cs +++ b/src/Core/ICredentialStore.cs @@ -7,6 +7,11 @@ namespace GitCredentialManager /// public interface ICredentialStore { + /// + /// Get the name of the credential store. + /// + string Name { get; } + /// /// Get all accounts from the store for the given service. /// diff --git a/src/Core/Interop/Linux/SecretServiceCollection.cs b/src/Core/Interop/Linux/SecretServiceCollection.cs index 0d6342af1d..20afc2341b 100644 --- a/src/Core/Interop/Linux/SecretServiceCollection.cs +++ b/src/Core/Interop/Linux/SecretServiceCollection.cs @@ -37,6 +37,8 @@ public SecretServiceCollection(string @namespace) #region ICredentialStore + public string Name => "freedesktop.org Secret Service"; + public IList GetAccounts(string service) { return Enumerate(service, null).Select(x => x.Account).Distinct().ToList(); diff --git a/src/Core/Interop/MacOS/MacOSKeychain.cs b/src/Core/Interop/MacOS/MacOSKeychain.cs index 9335e136d8..2aa0474cbc 100644 --- a/src/Core/Interop/MacOS/MacOSKeychain.cs +++ b/src/Core/Interop/MacOS/MacOSKeychain.cs @@ -31,6 +31,8 @@ public MacOSKeychain(string @namespace = null) #region ICredentialStore + public string Name => "macOS Keychain"; + public IList GetAccounts(string service) { IntPtr query = IntPtr.Zero; diff --git a/src/Core/Interop/Posix/GpgPassCredentialStore.cs b/src/Core/Interop/Posix/GpgPassCredentialStore.cs index debc9c8153..3b6b3edbab 100644 --- a/src/Core/Interop/Posix/GpgPassCredentialStore.cs +++ b/src/Core/Interop/Posix/GpgPassCredentialStore.cs @@ -19,6 +19,8 @@ public GpgPassCredentialStore(IFileSystem fileSystem, IGpg gpg, string storeRoot _gpg = gpg; } + public override string Name => "GPG/Pass"; + protected override string CredentialFileExtension => ".gpg"; private string GetGpgId(string credentialFullPath) diff --git a/src/Core/Interop/Windows/DpapiCredentialStore.cs b/src/Core/Interop/Windows/DpapiCredentialStore.cs index 8e468aeb1d..f5259cd776 100644 --- a/src/Core/Interop/Windows/DpapiCredentialStore.cs +++ b/src/Core/Interop/Windows/DpapiCredentialStore.cs @@ -14,6 +14,8 @@ public DpapiCredentialStore(IFileSystem fileSystem, string storeRoot, string @na PlatformUtils.EnsureWindows(); } + public override string Name => "DPAPI"; + protected override bool TryDeserializeCredential(string path, out FileCredential credential) { string text; diff --git a/src/Core/Interop/Windows/WindowsCredentialManager.cs b/src/Core/Interop/Windows/WindowsCredentialManager.cs index f577ad3010..ea0d260fc6 100644 --- a/src/Core/Interop/Windows/WindowsCredentialManager.cs +++ b/src/Core/Interop/Windows/WindowsCredentialManager.cs @@ -24,6 +24,8 @@ public WindowsCredentialManager(string @namespace = null) _namespace = @namespace; } + public string Name => "Windows Credential Manager"; + public IList GetAccounts(string service) { return Enumerate(service, null).Select(x => x.UserName).Distinct().ToList(); diff --git a/src/Core/NullCredentialStore.cs b/src/Core/NullCredentialStore.cs index fac92f47cb..d3dc1c58ea 100644 --- a/src/Core/NullCredentialStore.cs +++ b/src/Core/NullCredentialStore.cs @@ -9,6 +9,8 @@ namespace GitCredentialManager; /// public class NullCredentialStore : ICredentialStore { + public string Name => "No-op"; + public IList GetAccounts(string service) => Array.Empty(); public ICredential Get(string service, string account) => null; diff --git a/src/Core/PlaintextCredentialStore.cs b/src/Core/PlaintextCredentialStore.cs index e88861c492..d9de85aba3 100644 --- a/src/Core/PlaintextCredentialStore.cs +++ b/src/Core/PlaintextCredentialStore.cs @@ -23,6 +23,8 @@ public PlaintextCredentialStore(IFileSystem fileSystem, string storeRoot, string protected string Namespace { get; } protected virtual string CredentialFileExtension => ".credential"; + public virtual string Name => "Plaintext"; + public IList GetAccounts(string service) { return Enumerate(service, null).Select(x => x.Account).Distinct().ToList(); diff --git a/src/TestInfrastructure/Objects/TestCredentialStore.cs b/src/TestInfrastructure/Objects/TestCredentialStore.cs index 6ef1e18667..bcb5dc756d 100644 --- a/src/TestInfrastructure/Objects/TestCredentialStore.cs +++ b/src/TestInfrastructure/Objects/TestCredentialStore.cs @@ -14,6 +14,8 @@ public TestCredentialStore() #region ICredentialStore + public string Name => "Test Credential Store"; + public IList GetAccounts(string service) { return Query(service, null).Select(x => x.Account).Distinct().ToList(); From 9da5dbdb914dc8b6aa144815281b4667c816a48d Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Thu, 27 Aug 2026 17:52:10 +0100 Subject: [PATCH 2/2] diagnose: report actual credential store Report the actual credential backing store name rather than the runtime type (which is always `CredentialStore`; and not helpful). Signed-off-by: Matthew John Cheetham --- src/Core/Diagnostics/CredentialStoreDiagnostic.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Diagnostics/CredentialStoreDiagnostic.cs b/src/Core/Diagnostics/CredentialStoreDiagnostic.cs index 74f9ca2edc..c5c8fac701 100644 --- a/src/Core/Diagnostics/CredentialStoreDiagnostic.cs +++ b/src/Core/Diagnostics/CredentialStoreDiagnostic.cs @@ -13,7 +13,7 @@ public CredentialStoreDiagnostic(ICommandContext commandContext) protected override Task RunInternalAsync(StringBuilder log, IList additionalFiles) { - log.AppendLine($"ICredentialStore instance is of type: {CommandContext.CredentialStore.GetType().Name}"); + log.AppendLine($"Credential store is: {CommandContext.CredentialStore.Name}"); // Create a service that is guaranteed to be unique string service = $"https://example.com/{Guid.NewGuid():N}";