Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 9 additions & 23 deletions src/CredentialManager/CredentialManager.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
using System.Collections.Generic;

namespace GitCredentialManager;

public interface ICredentialManager : ICredentialStore
{
ICommandContext Context { get; }
}
namespace GitCredentialManager;

/// <summary>
/// Provides the factory method <see cref="Create"/> to instantiate a
Expand All @@ -24,20 +17,13 @@ public static class CredentialManager
/// </summary>
/// <param name="namespace">Optional namespace to scope credential operations.</param>
/// <returns>The <see cref="ICredentialStore"/>.</returns>
public static ICredentialManager Create(string? @namespace = default)
{
// The context already does the check for the platform and configured store to initialize.
// By overriding the settings with our wrapper, we ensure just the namespace is overriden.
var context = new CommandContextWrapper(new CommandContext(), @namespace);
return new CredentialManagerStore(new CredentialStore(context), context);
}
public static ICredentialStore Create(string? @namespace = default)
=> CreateContext(@namespace).CredentialStore;

class CredentialManagerStore(ICredentialStore store, ICommandContext context) : ICredentialManager
{
public ICommandContext Context => context;
public void AddOrUpdate(string service, string account, string secret) => store.AddOrUpdate(service, account, secret);
public ICredential Get(string service, string account) => store.Get(service, account);
public IList<string> GetAccounts(string service) => store.GetAccounts(service);
public bool Remove(string service, string account) => store.Remove(service, account);
}
/// <summary>
/// Creates a new <see cref="ICommandContext"/> that can be used for GCM operations
/// without depending on a git installation.
/// </summary>
public static ICommandContext CreateContext(string? @namespace = default)
=> new CommandContextAdapter(new CommandContext(), @namespace);
}
42 changes: 30 additions & 12 deletions src/CredentialManager/NoGitWrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,36 @@ namespace GitCredentialManager;
/// A wrapper for <see cref="ICommandContext"/> that overrides the namespace for credentials and also
/// allows git-less usage except for the git cache store.
/// </summary>
class CommandContextWrapper(CommandContext context, string? @namespace) : ICommandContext
class CommandContextAdapter : ICommandContext
{
readonly ISettings settings = new SettingsWrapper(
context.Settings is WindowsSettings ?
new NoGitWindowsSettings(context.Environment, context.Git, context.Trace) :
new NoGitSettings(context.Environment, context.Git), @namespace);
readonly CommandContext context;
readonly ICredentialStore store;
readonly ISettings settings;
readonly IHttpClientFactory clientFactory;

public CommandContextAdapter(CommandContext context, string? @namespace = default)
{
this.context = context;

store = new CredentialStore(this);

settings = new SettingsAdapter(
context.Settings is WindowsSettings ?
new NoGitWindowsSettings(context.Environment, context.Git, context.Trace) :
new NoGitSettings(context.Environment, context.Git), @namespace);

clientFactory = new HttpClientFactory(
context.FileSystem, context.Trace, context.Trace2, settings, context.Streams);
}

public ISettings Settings => settings;

public ICredentialStore CredentialStore => store;

public IHttpClientFactory HttpClientFactory => clientFactory;

public IGit Git => new NoGit(context.Git);

#region pass-through impl.

public string ApplicationPath { get => ((ICommandContext)context).ApplicationPath; set => ((ICommandContext)context).ApplicationPath = value; }
Expand All @@ -40,12 +61,6 @@ context.Settings is WindowsSettings ?

public IFileSystem FileSystem => ((ICommandContext)context).FileSystem;

public ICredentialStore CredentialStore => ((ICommandContext)context).CredentialStore;

public IHttpClientFactory HttpClientFactory => ((ICommandContext)context).HttpClientFactory;

public IGit Git => new NoGit(context.Git);

public IEnvironment Environment => ((ICommandContext)context).Environment;

public IProcessManager ProcessManager => ((ICommandContext)context).ProcessManager;
Expand Down Expand Up @@ -137,11 +152,14 @@ public bool TryGet(GitConfigurationLevel level, GitConfigurationType type, strin
}
}

/// <summary>Adapts <see cref="Settings"/> to use <see cref="NoGit"/>.</summary>
class NoGitSettings(IEnvironment environment, IGit git) : Settings(environment, new NoGit(git)) { }

/// <summary>Adapts <see cref="WindowsSettings"/> to use <see cref="NoGit"/>.</summary>
class NoGitWindowsSettings(IEnvironment environment, IGit git, ITrace trace) : WindowsSettings(environment, new NoGit(git), trace) { }

class SettingsWrapper(ISettings settings, string? @namespace) : ISettings
/// <summary>Allows overriding the credential namespace.</summary>
class SettingsAdapter(ISettings settings, string? @namespace) : ISettings
{
public string CredentialNamespace => @namespace ?? settings.CredentialNamespace;

Expand Down
Loading