Skip to content

Commit

Permalink
git: drop config --show-scope option usage
Browse files Browse the repository at this point in the history
The Git config `--show-scope` option was only introduced in Git from
version 2.26 onwards. The latest version of Git available in some
distributions of Linux (or macOS) is often older.

We only needed to know the scope of configuration values in one
particular call site: reading all Azure Repos user bindinds.

Replace the single `IGitConfiguration::Enumerate` call with two calls to
`Enumerate`, one for the global scope, and one for the local one.

Drop the --show-scope option parsing.
  • Loading branch information
mjcheetham committed Mar 24, 2021
1 parent d1cb371 commit 5dda6a6
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 61 deletions.
44 changes: 23 additions & 21 deletions src/shared/Microsoft.AzureRepos/AzureReposBindingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,31 +174,33 @@ public IEnumerable<AzureReposBinding> GetBindings(string orgName = null)

string orgPrefix = $"{AzureDevOpsConstants.UrnOrgPrefix}/";

config.Enumerate(
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.UserName,
entry =>
bool ExtractUserBinding(GitConfigurationEntry entry, IDictionary<string, string> dict)
{
if (GitConfigurationKeyComparer.TrySplit(entry.Key, out _, out string scope, out _) &&
Uri.TryCreate(scope, UriKind.Absolute, out Uri uri) &&
uri.Scheme == AzureDevOpsConstants.UrnScheme && uri.AbsolutePath.StartsWith(orgPrefix))
{
if (GitConfigurationKeyComparer.TrySplit(entry.Key, out _, out string scope, out _) &&
Uri.TryCreate(scope, UriKind.Absolute, out Uri uri) &&
uri.Scheme == AzureDevOpsConstants.UrnScheme && uri.AbsolutePath.StartsWith(orgPrefix))
string entryOrgName = uri.AbsolutePath.Substring(orgPrefix.Length);
if (orgName is null || StringComparer.OrdinalIgnoreCase.Equals(entryOrgName, orgName))
{
string entryOrgName = uri.AbsolutePath.Substring(orgPrefix.Length);
if (orgName is null || StringComparer.OrdinalIgnoreCase.Equals(entryOrgName, orgName))
{
if (entry.Level == GitConfigurationLevel.Local)
{
localUsers[entryOrgName] = entry.Value;
}
else
{
globalUsers[entryOrgName] = entry.Value;
}
}
dict[entryOrgName] = entry.Value;
}
}

return true;
}

return true;
});
config.Enumerate(
GitConfigurationLevel.Local,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.UserName,
entry => ExtractUserBinding(entry, localUsers));

config.Enumerate(
GitConfigurationLevel.Global,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.UserName,
entry => ExtractUserBinding(entry, globalUsers));

foreach (string org in globalUsers.Keys.Union(localUsers.Keys))
{
Expand Down
38 changes: 2 additions & 36 deletions src/shared/Microsoft.Git.CredentialManager/GitConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ internal GitProcessConfiguration(ITrace trace, GitProcess git)
public void Enumerate(GitConfigurationLevel level, GitConfigurationEnumerationCallback cb)
{
string levelArg = GetLevelFilterArg(level);
using (Process git = _git.CreateProcess($"config --null {levelArg} --list --show-scope"))
using (Process git = _git.CreateProcess($"config --null {levelArg} --list"))
{
git.Start();
// To avoid deadlocks, always read the output stream first and then wait
Expand All @@ -134,31 +134,14 @@ public void Enumerate(GitConfigurationLevel level, GitConfigurationEnumerationCa
throw GitProcess.CreateGitException(git, "Failed to enumerate all Git configuration entries");
}

var scope = new StringBuilder();
var name = new StringBuilder();
var value = new StringBuilder();
int i = 0;
while (i < data.Length)
{
scope.Clear();
name.Clear();
value.Clear();

// Read config scope (null terminated)
while (i < data.Length && data[i] != '\0')
{
scope.Append(data[i++]);
}

if (i >= data.Length)
{
_trace.WriteLine("Invalid Git configuration output. Expected null terminator (\\0) after scope.");
break;
}

// Skip the null terminator
i++;

// Read key name (LF terminated)
while (i < data.Length && data[i] != '\n')
{
Expand Down Expand Up @@ -189,24 +172,7 @@ public void Enumerate(GitConfigurationLevel level, GitConfigurationEnumerationCa
// Skip the null terminator
i++;

GitConfigurationLevel entryLevel;
switch (scope.ToString())
{
case "system":
entryLevel = GitConfigurationLevel.System;
break;
case "global":
entryLevel = GitConfigurationLevel.Global;
break;
case "local":
entryLevel = GitConfigurationLevel.Local;
break;
default:
entryLevel = GitConfigurationLevel.Unknown;
break;
}

var entry = new GitConfigurationEntry(entryLevel, name.ToString(), value.ToString());
var entry = new GitConfigurationEntry(name.ToString(), value.ToString());

if (!cb(entry))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ namespace Microsoft.Git.CredentialManager
{
public class GitConfigurationEntry
{
public GitConfigurationEntry(GitConfigurationLevel level, string key, string value)
public GitConfigurationEntry(string key, string value)
{
Level = level;
Key = key;
Value = value;
}

public GitConfigurationLevel Level { get; }
public string Key { get; }
public string Value { get; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void Enumerate(GitConfigurationLevel level, GitConfigurationEnumerationCa
{
foreach (var value in kvp.Value)
{
var entry = new GitConfigurationEntry(dictLevel, kvp.Key, value);
var entry = new GitConfigurationEntry(kvp.Key, value);
if (!cb(entry))
{
break;
Expand Down

0 comments on commit 5dda6a6

Please sign in to comment.