Skip to content

Commit 14bd2b6

Browse files
committed
fix config provider file system lookups so that we're actually using data from them
1 parent 095ae08 commit 14bd2b6

File tree

4 files changed

+25
-91
lines changed

4 files changed

+25
-91
lines changed

src/Microsoft.Extensions.Configuration.DotnetCli/DotNetConfigurationFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ private static DotNetCliConfiguration CreateInternal(string? workingDirectory)
5454
workingDirectory ??= Directory.GetCurrentDirectory();
5555

5656
var configurationBuilder = new ConfigurationBuilder();
57+
configurationBuilder.SetBasePath(workingDirectory);
5758

5859
// Configuration sources are added in reverse precedence order
5960
// Last added has highest precedence

src/Microsoft.Extensions.Configuration.DotnetCli/Providers/DotNetConfigurationSource.cs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ public class DotNetConfigurationSource : IniConfigurationSource
1212
{
1313
public DotNetConfigurationSource(string workingDirectory)
1414
{
15-
Path = FindDotNetConfigPath(workingDirectory);
15+
Path = System.IO.Path.Combine(workingDirectory, "dotnet.config");
1616
Optional = true; // Make it optional since dotnet.config may not exist
17+
ResolveFileProvider();
1718
}
1819
/// <summary>
1920
/// Builds the configuration provider for dotnet.config files.
@@ -25,21 +26,4 @@ public override IConfigurationProvider Build(IConfigurationBuilder builder)
2526
EnsureDefaults(builder);
2627
return new DotNetConfigurationProvider(this);
2728
}
28-
29-
private static string FindDotNetConfigPath(string? workingDirectory = null)
30-
{
31-
string? directory = workingDirectory ?? Directory.GetCurrentDirectory();
32-
// Search for dotnet.config in the current directory and upwards
33-
while (directory != null)
34-
{
35-
string dotnetConfigPath = System.IO.Path.Combine(directory, "dotnet.config");
36-
if (File.Exists(dotnetConfigPath))
37-
{
38-
return dotnetConfigPath;
39-
}
40-
41-
directory = System.IO.Path.GetDirectoryName(directory);
42-
}
43-
return "dotnet.config"; // Return default path even if not found
44-
}
4529
}
Lines changed: 13 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Text.Json;
4+
using Microsoft.Extensions.Configuration.Json;
55

66
namespace Microsoft.Extensions.Configuration.DotnetCli.Providers;
77

88
/// <summary>
99
/// Configuration provider that reads global.json files and maps keys to the canonical format.
1010
/// </summary>
11-
public class GlobalJsonConfigurationProvider : ConfigurationProvider
11+
public class GlobalJsonConfigurationProvider : JsonConfigurationProvider
1212
{
13-
private readonly string? _path;
14-
1513
private static readonly Dictionary<string, string> GlobalJsonKeyMappings = new()
1614
{
1715
["sdk:version"] = "sdk:version",
@@ -21,54 +19,26 @@ public class GlobalJsonConfigurationProvider : ConfigurationProvider
2119
// Add more mappings as the global.json schema evolves
2220
};
2321

24-
public GlobalJsonConfigurationProvider(string workingDirectory)
22+
public GlobalJsonConfigurationProvider(GlobalJsonConfigurationSource source) : base(source)
2523
{
26-
_path = FindGlobalJson(workingDirectory);
2724
}
2825

2926
public override void Load()
3027
{
31-
Data.Clear();
32-
33-
if (_path == null || !File.Exists(_path))
34-
return;
28+
base.Load();
29+
// Transform keys according to our mapping
30+
var transformedData = new Dictionary<string, string?>(Data.Count, StringComparer.OrdinalIgnoreCase);
3531

36-
try
37-
{
38-
var json = File.ReadAllText(_path);
39-
var document = JsonDocument.Parse(json);
40-
41-
LoadGlobalJsonData(document.RootElement, "");
42-
}
43-
catch (Exception ex)
32+
foreach (var kvp in Data)
4433
{
45-
throw new InvalidOperationException($"Error parsing global.json at {_path}", ex);
34+
string key = kvp.Key;
35+
string? value = kvp.Value;
36+
var mappedKey = MapGlobalJsonKey(key);
37+
transformedData[mappedKey] = value;
4638
}
47-
}
4839

49-
private void LoadGlobalJsonData(JsonElement element, string prefix)
50-
{
51-
foreach (var property in element.EnumerateObject())
52-
{
53-
var rawKey = string.IsNullOrEmpty(prefix)
54-
? property.Name
55-
: $"{prefix}:{property.Name}";
56-
57-
switch (property.Value.ValueKind)
58-
{
59-
case JsonValueKind.Object:
60-
LoadGlobalJsonData(property.Value, rawKey);
61-
break;
62-
case JsonValueKind.String:
63-
case JsonValueKind.Number:
64-
case JsonValueKind.True:
65-
case JsonValueKind.False:
66-
// Map to canonical key format
67-
var canonicalKey = MapGlobalJsonKey(rawKey);
68-
Data[canonicalKey] = GetValueAsString(property.Value);
69-
break;
70-
}
71-
}
40+
// Replace the data with transformed keys
41+
Data = transformedData;
7242
}
7343

7444
private string MapGlobalJsonKey(string rawKey)
@@ -84,29 +54,4 @@ private string MapGlobalJsonKey(string rawKey)
8454
// Default: convert to lowercase and normalize separators
8555
return rawKey.ToLowerInvariant().Replace("-", ":");
8656
}
87-
88-
private string GetValueAsString(JsonElement element)
89-
{
90-
return element.ValueKind switch
91-
{
92-
JsonValueKind.String => element.GetString()!,
93-
JsonValueKind.Number => element.GetRawText(),
94-
JsonValueKind.True => "true",
95-
JsonValueKind.False => "false",
96-
_ => element.GetRawText()
97-
};
98-
}
99-
100-
private string? FindGlobalJson(string startDirectory)
101-
{
102-
var current = new DirectoryInfo(startDirectory);
103-
while (current != null)
104-
{
105-
var globalJsonPath = Path.Combine(current.FullName, "global.json");
106-
if (File.Exists(globalJsonPath))
107-
return globalJsonPath;
108-
current = current.Parent;
109-
}
110-
return null;
111-
}
11257
}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.Extensions.Configuration.Json;
5+
46
namespace Microsoft.Extensions.Configuration.DotnetCli.Providers;
57

68
/// <summary>
79
/// Configuration source for global.json files.
810
/// </summary>
9-
public class GlobalJsonConfigurationSource : IConfigurationSource
11+
public class GlobalJsonConfigurationSource : JsonConfigurationSource
1012
{
11-
private readonly string _workingDirectory;
1213

1314
public GlobalJsonConfigurationSource(string workingDirectory)
1415
{
15-
_workingDirectory = workingDirectory ?? throw new ArgumentNullException(nameof(workingDirectory));
16+
Path = System.IO.Path.Combine(workingDirectory, "global.json");
17+
Optional = true;
18+
ResolveFileProvider();
1619
}
1720

18-
public IConfigurationProvider Build(IConfigurationBuilder builder)
21+
public override IConfigurationProvider Build(IConfigurationBuilder builder)
1922
{
20-
return new GlobalJsonConfigurationProvider(_workingDirectory);
23+
EnsureDefaults(builder);
24+
return new GlobalJsonConfigurationProvider(this);
2125
}
2226
}

0 commit comments

Comments
 (0)