@@ -86,6 +86,40 @@ public void GnuPassCredentialStore_Remove_NotFound_ReturnsFalse()
8686 Assert . False ( result ) ;
8787 }
8888
89+ [ PosixFact ]
90+ public void GnuPassCredentialStore_ReadWriteDelete_GpgIdInSubdirectory ( )
91+ {
92+ var fs = new TestFileSystem ( ) ;
93+ var gpg = new TestGpg ( fs ) ;
94+ string storeRoot = InitializePasswordStoreWithGpgIdInSubdirectory ( fs , gpg , TestNamespace ) ;
95+
96+ var collection = new GpgPassCredentialStore ( fs , gpg , storeRoot , TestNamespace ) ;
97+
98+ // Create a service that is guaranteed to be unique
99+ string uniqueGuid = Guid . NewGuid ( ) . ToString ( "N" ) ;
100+ string service = $ "https://example.com/{ uniqueGuid } ";
101+ const string userName = "john.doe" ;
102+ const string password = "letmein123" ; // [SuppressMessage("Microsoft.Security", "CS001:SecretInline", Justification="Fake credential")]
103+
104+ try
105+ {
106+ // Write
107+ collection . AddOrUpdate ( service , userName , password ) ;
108+
109+ // Read
110+ ICredential outCredential = collection . Get ( service , userName ) ;
111+
112+ Assert . NotNull ( outCredential ) ;
113+ Assert . Equal ( userName , outCredential . Account ) ;
114+ Assert . Equal ( password , outCredential . Password ) ;
115+ }
116+ finally
117+ {
118+ // Ensure we clean up after ourselves even in case of 'get' failures
119+ collection . Remove ( service , userName ) ;
120+ }
121+ }
122+
89123 private static string InitializePasswordStore ( TestFileSystem fs , TestGpg gpg )
90124 {
91125 string homePath = Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) ;
@@ -102,5 +136,27 @@ private static string InitializePasswordStore(TestFileSystem fs, TestGpg gpg)
102136
103137 return storePath ;
104138 }
139+
140+ private static string InitializePasswordStoreWithGpgIdInSubdirectory ( TestFileSystem fs , TestGpg gpg , string subdirectory )
141+ {
142+ string homePath = Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) ;
143+ string storePath = Path . Combine ( homePath , ".password-store" ) ;
144+ string userId = "gcm-test@example.com" ;
145+
146+ // Place .gpg-id only in the namespace subdirectory (not the store root),
147+ // simulating a pass store where the root has no .gpg-id but submodules do.
148+ string subDirPath = Path . Combine ( storePath , subdirectory ) ;
149+ string gpgIdPath = Path . Combine ( subDirPath , ".gpg-id" ) ;
150+
151+ // Ensure we have a GPG key for use with testing
152+ gpg . GenerateKeys ( userId ) ;
153+
154+ // Init the password store with .gpg-id only in the subdirectory
155+ fs . Directories . Add ( storePath ) ;
156+ fs . Directories . Add ( subDirPath ) ;
157+ fs . Files [ gpgIdPath ] = Encoding . UTF8 . GetBytes ( userId ) ;
158+
159+ return storePath ;
160+ }
105161 }
106162}
0 commit comments