Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Take affected projects in consideration when updating dotnet-ef #164

Merged
merged 2 commits into from
Sep 19, 2024
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
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
Expand Down
1 change: 1 addition & 0 deletions src/Build/docs/release-notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bug: `dotnet-ef` didn't always get updated in `.config/dotnet-tools.json`
25 changes: 23 additions & 2 deletions src/UpdatR/Domain/Csproj.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,14 @@ public static Csproj Create(string path)
CheckForDeprecationAndVulnerabilities(project, packageId, updateTo);
}

if (!dryRun && changed)
if (changed)
{
doc.Save(Path);
if (!dryRun)
{
doc.Save(Path);
}

UpdateEntityFrameworkVersion();
}

return project.AnyPackages() ? project : null;
Expand Down Expand Up @@ -196,6 +201,22 @@ private NuGetFramework GetTargetFramework()
: NuGetFramework.Parse(targetFramework);
}

private void UpdateEntityFrameworkVersion()
{
foreach (var (packageId, version) in Packages)
{
if (
packageId.StartsWith(
"Microsoft.EntityFrameworkCore",
StringComparison.OrdinalIgnoreCase
)
)
{
_entityFrameworkVersion = version;
}
}
}

private NuGetVersion? GetEntityFrameworkVersion()
{
foreach (var (packageId, version) in Packages)
Expand Down
10 changes: 6 additions & 4 deletions src/UpdatR/Domain/DotnetTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal sealed partial class DotnetTools
{
private readonly FileInfo _path;
private static readonly JsonSerializerOptions s_jsonSerializerOptions =
new JsonSerializerOptions(JsonSerializerDefaults.Web) { WriteIndented = true, };
new(JsonSerializerDefaults.Web) { WriteIndented = true, };

private DotnetTools(FileInfo path)
{
Expand All @@ -24,11 +24,13 @@ private DotnetTools(FileInfo path)

public string Parent => _path.DirectoryName!;

public NuGetVersion? HighestAllowedDotnetEf { get; init; }
public NuGetVersion? HighestAllowedDotnetEf => AffectedCsprojs.Min(x => x.EntityFrameworkVersion);

public IEnumerable<Csproj> AffectedCsprojs { get; init; } = [];

public IEnumerable<string> PackageIds => GetPackageIds();

public static DotnetTools Create(string path, NuGetVersion? highestAllowedDotnetEf)
public static DotnetTools Create(string path, IEnumerable<Csproj> affectedCsprojs)
{
if (string.IsNullOrWhiteSpace(path))
{
Expand All @@ -55,7 +57,7 @@ public static DotnetTools Create(string path, NuGetVersion? highestAllowedDotnet

return new DotnetTools(new(System.IO.Path.GetFullPath(path)))
{
HighestAllowedDotnetEf = highestAllowedDotnetEf,
AffectedCsprojs = affectedCsprojs,
};
}

Expand Down
73 changes: 43 additions & 30 deletions src/UpdatR/Domain/RootDir.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Text.RegularExpressions;
using NuGet.Versioning;
using NuGet.Packaging;

namespace UpdatR.Domain;

Expand All @@ -20,12 +20,12 @@ private RootDir(DirectoryInfo path)

public void AddDotnetTools(DotnetTools dotnetTools)
{
(DotnetTools ??= new HashSet<DotnetTools>()).Add(dotnetTools);
(DotnetTools ??= []).Add(dotnetTools);
}

public void AddCsproj(Csproj csproj)
{
(Csprojs ??= new HashSet<Csproj>()).Add(csproj);
(Csprojs ??= []).Add(csproj);
}

public static RootDir Create(string path)
Expand Down Expand Up @@ -88,7 +88,7 @@ var configFile in Directory.EnumerateFiles(
{
var config = Domain.DotnetTools.Create(
configFile,
GetEfVersionBasedOnCsproj(new FileInfo(configFile).Directory!.Parent!.FullName)
dir.Csprojs ?? GetProjectsRecursiveFromParent(path)
);

dir.AddDotnetTools(config);
Expand Down Expand Up @@ -118,6 +118,11 @@ private static RootDir CreateFromFile(FileInfo path)

AddDotnetToolsFromCsproj(dir);

foreach (var item in GetDotnetToolsConfigFromSolution(path, dir.Csprojs ?? []))
{
dir.AddDotnetTools(item);
}

return dir;
}

Expand All @@ -134,13 +139,14 @@ private static RootDir CreateFromFile(FileInfo path)

if (path.Name.Equals("dotnet-tools.json", StringComparison.OrdinalIgnoreCase))
{
var projects = GetProjectsRecursiveFromParent(path.Directory!);

var dir = new RootDir(path.Directory!);
;

dir.AddDotnetTools(
Domain.DotnetTools.Create(
path.FullName,
GetEfVersionBasedOnCsproj(path.Directory!.Parent!.FullName)
projects
)
);

Expand All @@ -167,41 +173,35 @@ static void AddDotnetToolsFromCsproj(RootDir dir)
dir.AddDotnetTools(
Domain.DotnetTools.Create(
configPath,
GetEfVersionBasedOnCsproj(
new FileInfo(configPath).Directory!.Parent!.FullName
)
dir.Csprojs ?? []
)
);
}
}
}

private static NuGetVersion? GetEfVersionBasedOnCsproj(string path)
private static HashSet<Csproj> GetProjectsRecursiveFromParent(DirectoryInfo path)
{
foreach (
var projectFile in Directory.EnumerateFiles(
path,
"*.csproj",
new EnumerationOptions
{
MatchCasing = MatchCasing.CaseInsensitive,
RecurseSubdirectories = true,
MaxRecursionDepth = 1,
}
)
)
{
var csproj = Csproj.Create(projectFile);
var isInConfigFolder = path.Name.Equals(".config", StringComparison.OrdinalIgnoreCase);

var efVersion = csproj.EntityFrameworkVersion;
HashSet<Csproj> projects = [];

if (efVersion is not null)
{
return efVersion;
}
if (isInConfigFolder)
{
projects.AddRange(
Directory.EnumerateFiles(
path.Parent!.FullName,
"*.csproj",
new EnumerationOptions
{
MatchCasing = MatchCasing.CaseInsensitive,
RecurseSubdirectories = true
}
)
.Select(Csproj.Create));
}

return null;
return projects;
}

private static IEnumerable<Csproj> GetProjectsFromSolution(FileInfo solution) =>
Expand All @@ -216,4 +216,17 @@ private static IEnumerable<Csproj> GetProjectsFromSolution(FileInfo solution) =>
.Select(x => new FileInfo(x))
.Where(x => x.Exists)
.Select(x => Csproj.Create(x.FullName));

private static IEnumerable<DotnetTools> GetDotnetToolsConfigFromSolution(FileInfo solution, IEnumerable<Csproj> csprojs) =>
Regex
.Matches(
File.ReadAllText(solution.FullName),
"""(?<File>\.config\\dotnet-tools\.json)(?= =)""",
RegexOptions.Multiline
)
.Select(x => System.IO.Path.Combine(x.Groups["File"].Value))
.Select(x => System.IO.Path.Combine(solution.DirectoryName!, x))
.Select(x => new FileInfo(x))
.Where(x => x.Exists)
.Select(x => Domain.DotnetTools.Create(x.FullName, csprojs));
}
12 changes: 6 additions & 6 deletions src/UpdatR/Internals/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace UpdatR.Internals;

internal sealed class Result
{
private readonly List<(string Name, string Source)> _unauthorizedSources = new();
private readonly List<(string Name, string Source)> _unauthorizedSources = [];
private readonly Dictionary<string, HashSet<string>> _unknownPackages =
new(StringComparer.OrdinalIgnoreCase);
private readonly string _rootPath;
Expand Down Expand Up @@ -82,18 +82,18 @@ internal bool TryAddUnknownPackage(string packageId, string project)
}
else
{
_unknownPackages[packageId] = new HashSet<string> { project };
_unknownPackages[packageId] = [project];
}
return true;
}
}

internal sealed record ProjectWithPackages
{
private readonly HashSet<string> _unknownPackages = new();
private readonly List<UpdatedPackage> _updatedPackages = new();
private readonly List<DeprecatedPackage> _deprecatedPackages = new();
private readonly List<VulnerablePackage> _vulnerablePackages = new();
private readonly HashSet<string> _unknownPackages = [];
private readonly List<UpdatedPackage> _updatedPackages = [];
private readonly List<DeprecatedPackage> _deprecatedPackages = [];
private readonly List<VulnerablePackage> _vulnerablePackages = [];

public string Path { get; init; }
public IEnumerable<string> UnknownPackages => _unknownPackages;
Expand Down
11 changes: 3 additions & 8 deletions tests/UpdatR.IntegrationTests/FileCreationUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,9 @@ params KeyValuePair<string, string>[] packages

private static string GetResource(string resourceName)
{
using var stream = typeof(FileCreationUtils).Assembly.GetManifestResourceStream(
resourceName
);

if (stream is null)
{
throw new InvalidOperationException($"'{resourceName} is not an embedded resource.");
}
using var stream =
typeof(FileCreationUtils).Assembly.GetManifestResourceStream(resourceName)
?? throw new InvalidOperationException($"'{resourceName} is not an embedded resource.");

using var reader = new StreamReader(stream);

Expand Down
5 changes: 5 additions & 0 deletions tests/UpdatR.IntegrationTests/Resources/Templates/Dummy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{D2CF3675-9F2F-47F3-98C8-30FBB35E6088}"
ProjectSection(SolutionItems) = preProject
.config\dotnet-tools.json = .config\dotnet-tools.json
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "<PROJECTNAME>", "<PROJECTPATH>", "{24D4763A-A7DD-40B6-B973-7565FD8F80E6}"
EndProject
Global
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Updates: [
{
Item1: 5.0.5,
Item2: 5.0.12,
Item2: 5.0.16,
Item3: .config\dotnet-tools.json
}
]
Expand All @@ -41,7 +41,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.12",
"version": "5.0.16",
"commands": [
"dotnet"
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
[
[
{
PackageId: Microsoft.EntityFrameworkCore,
Updates: [
{
Item1: 5.0.5,
Item2: 5.0.16,
Item3: Dummy.App.csproj
}
]
},
{
PackageId: dotnet-ef,
Updates: [
{
Item1: 5.0.5,
Item2: 5.0.16,
Item3: .config\dotnet-tools.json
}
]
}
]

{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.5",
"commands": [
"dotnet"
]
}
}
}


{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.16",
"commands": [
"dotnet"
]
}
}
}


<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" />
</ItemGroup>
</Project>

<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.16" />
</ItemGroup>
</Project>
]
Loading