diff --git a/docs/enterprise-config.md b/docs/enterprise-config.md index bfdc7e302..97544a33f 100644 --- a/docs/enterprise-config.md +++ b/docs/enterprise-config.md @@ -55,7 +55,38 @@ those of the [Git configuration][config] settings. The type of each registry key can be either `REG_SZ` (string) or `REG_DWORD` (integer). -## macOS/Linux +## macOS + +Default settings values come from macOS's preferences system. Configuration +profiles can be deployed to devices using a compatible Mobile Device Management +(MDM) solution. + +Configuration for Git Credential Manager must take the form of a dictionary, set +for the domain `git-credential-manager` under the key `configuration`. For +example: + +```shell +defaults write git-credential-manager configuration -dict-add +``` + +..where `` is the name of the settings from the [Git configuration][config] +reference, and `` is the desired value. + +All values in the `configuration` dictionary must be strings. For boolean values +use `true` or `false`, and for integer values use the number in string form. + +To read the current configuration: + +```console +$ defaults read git-credential-manager configuration +{ + = ; + ... + = ; +} +``` + +## Linux Default configuration setting stores has not been implemented. diff --git a/src/shared/Core/CommandContext.cs b/src/shared/Core/CommandContext.cs index 712db32e1..d3ef1dbf6 100644 --- a/src/shared/Core/CommandContext.cs +++ b/src/shared/Core/CommandContext.cs @@ -131,7 +131,7 @@ public CommandContext() gitPath, FileSystem.GetCurrentDirectory() ); - Settings = new Settings(Environment, Git); + Settings = new MacOSSettings(Environment, Git, Trace); } else if (PlatformUtils.IsLinux()) { diff --git a/src/shared/Core/Interop/MacOS/MacOSSettings.cs b/src/shared/Core/Interop/MacOS/MacOSSettings.cs new file mode 100644 index 000000000..6f85ea9f3 --- /dev/null +++ b/src/shared/Core/Interop/MacOS/MacOSSettings.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; + +namespace GitCredentialManager.Interop.MacOS +{ + /// + /// Reads settings from Git configuration, environment variables, and defaults from the system. + /// + public class MacOSSettings : Settings + { + private readonly ITrace _trace; + + public MacOSSettings(IEnvironment environment, IGit git, ITrace trace) + : base(environment, git) + { + EnsureArgument.NotNull(trace, nameof(trace)); + _trace = trace; + + PlatformUtils.EnsureMacOS(); + } + + protected override bool TryGetExternalDefault(string section, string scope, string property, out string value) + { + value = null; + + try + { + // Check for app default preferences for our bundle ID. + // Defaults can be deployed system administrators via device management profiles. + var prefs = new MacOSPreferences("git-credential-manager"); // TODO: move to a constant + IDictionary dict = prefs.GetDictionary("configuration"); + + if (dict is null) + { + // No configuration key exists + return false; + } + + // Wrap the raw dictionary in one configured with the Git configuration key comparer. + // This means we can use the same key comparison rules as Git in our configuration plist dict, + // That is, sections and names are insensitive to case, but the scope is case-sensitive. + var config = new Dictionary(dict, GitConfigurationKeyComparer.Instance); + + string name = string.IsNullOrWhiteSpace(scope) + ? $"{section}.{property}" + : $"{section}.{scope}.{property}"; + + if (!config.TryGetValue(name, out value)) + { + // No property exists + return false; + } + + _trace.WriteLine($"Default setting found in app preferences: {name}={value}"); + return true; + } + catch (Exception ex) + { + // Reading defaults is not critical to the operation of the application + // so we can ignore any errors and just log the failure. + _trace.WriteLine("Failed to read default setting from app preferences."); + _trace.WriteException(ex); + return false; + } + } + } +}