private static void AppendAvailableStoreList(StringBuilder sb)
        {
            if (PlatformUtils.IsWindows())
            {
                sb.AppendFormat("  {1,-13} : Windows Credential Manager (not available over network/SSH sessions){0}",
                                Environment.NewLine, StoreNames.WindowsCredentialManager);

                sb.AppendFormat("  {1,-13} : DPAPI protected files{0}",
                                Environment.NewLine, StoreNames.Dpapi);
            }

            if (PlatformUtils.IsMacOS())
            {
                sb.AppendFormat("  {1,-13} : macOS Keychain{0}",
                                Environment.NewLine, StoreNames.MacOSKeychain);
            }

            if (PlatformUtils.IsLinux())
            {
                sb.AppendFormat("  {1,-13} : freedesktop.org Secret Service (requires graphical interface){0}",
                                Environment.NewLine, StoreNames.SecretService);
            }

            if (PlatformUtils.IsPosix())
            {
                sb.AppendFormat("  {1,-13} : GNU `pass` compatible credential storage (requires GPG and `pass`){0}",
                                Environment.NewLine, StoreNames.Gpg);
            }

            sb.AppendFormat("  {1,-13} : Git's in-memory credential cache{0}",
                            Environment.NewLine, StoreNames.Cache);

            sb.AppendFormat("  {1,-13} : store credentials in plain-text files (UNSECURE){0}",
                            Environment.NewLine, StoreNames.Plaintext);
        }
        private void ValidateGpgPass(out string storeRoot, out string execPath)
        {
            if (!PlatformUtils.IsPosix())
            {
                throw new Exception(
                          $"Can only use the '{StoreNames.Gpg}' credential store on POSIX systems." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            execPath = GetGpgPath();

            // If we are in a headless environment, and don't have the GPG_TTY or SSH_TTY
            // variables set, then error - we need a TTY device path for pin-entry to work headless.
            if (!_context.SessionManager.IsDesktopSession &&
                !_context.Environment.Variables.ContainsKey("GPG_TTY") &&
                !_context.Environment.Variables.ContainsKey("SSH_TTY"))
            {
                throw new Exception(
                          "GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            // Check for a redirected pass store location
            if (!_context.Settings.TryGetSetting(
                    GpgPassCredentialStore.PasswordStoreDirEnvar,
                    null, null,
                    out storeRoot))
            {
                // Use default store root at ~/.password-store
                storeRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".password-store");
            }

            // Check we have a GPG ID to sign credential files with
            string gpgIdFile = Path.Combine(storeRoot, ".gpg-id");

            if (!_context.FileSystem.FileExists(gpgIdFile))
            {
                throw new Exception(
                          $"Password store has not been initialized at '{storeRoot}'; run `pass init <gpg-id>` to initialize the store." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }
        }
        /// <summary>
        /// Ensure the store root directory exists. If it does not, create a new directory with
        /// permissions that only permit the owner to read/write/execute. Permissions on an existing
        /// directory are not modified.
        /// </summary>
        private void EnsureStoreRoot()
        {
            if (FileSystem.DirectoryExists(StoreRoot))
            {
                // Don't touch the permissions on the existing directory
                return;
            }

            FileSystem.CreateDirectory(StoreRoot);

            // We only set file system permissions on POSIX platforms
            if (!PlatformUtils.IsPosix())
            {
                return;
            }

            // Set store root permissions such that only the owner can read/write/execute
            var mode = Interop.Posix.Native.NativeFileMode.S_IRUSR |
                       Interop.Posix.Native.NativeFileMode.S_IWUSR |
                       Interop.Posix.Native.NativeFileMode.S_IXUSR;

            // Ignore the return code.. this is a best effort only
            Interop.Posix.Native.Stat.chmod(StoreRoot, mode);
        }