diff --git a/src/PackageUpdate/FileSystem.cs b/src/PackageUpdate/FileSystem.cs index 934a05c..d0c37c3 100644 --- a/src/PackageUpdate/FileSystem.cs +++ b/src/PackageUpdate/FileSystem.cs @@ -1,5 +1,25 @@ static class FileSystem { + public static string? FindPropsFile(string startDirectory, string stopDirectory) + { + var stop = Path.TrimEndingDirectorySeparator(Path.GetFullPath(stopDirectory)); + for (var current = new DirectoryInfo(startDirectory); current is not null; current = current.Parent) + { + var candidate = Path.Combine(current.FullName, "Directory.Packages.props"); + if (File.Exists(candidate)) + { + return candidate; + } + + if (string.Equals(current.FullName, stop, StringComparison.OrdinalIgnoreCase)) + { + break; + } + } + + return null; + } + public static IEnumerable FindSolutions(string directory) { foreach (var solution in EnumerateFiles(directory, "*.sln")) @@ -61,4 +81,4 @@ static IEnumerable GetDirectories(string directory) return []; } } -} \ No newline at end of file +} diff --git a/src/PackageUpdate/Program.cs b/src/PackageUpdate/Program.cs index 3feb635..bee347d 100644 --- a/src/PackageUpdate/Program.cs +++ b/src/PackageUpdate/Program.cs @@ -28,7 +28,7 @@ static async Task Inner(string directory, string? package, bool build) continue; } - await TryProcessSolution(cache, solution, package, build); + await TryProcessSolution(cache, solution, package, build, directory); } // Tool manifests are scanned independently of solutions, since `.config/dotnet-tools.json` @@ -52,11 +52,11 @@ static async Task Inner(string directory, string? package, bool build) Log.Information("Completed in {Elapsed}", Formatter.FormatElapsed(totalStopwatch.Elapsed)); } -static async Task TryProcessSolution(SourceCacheContext cache, string solution, string? package, bool build) +static async Task TryProcessSolution(SourceCacheContext cache, string solution, string? package, bool build, string targetDirectory) { try { - await ProcessSolution(cache, solution, package, build); + await ProcessSolution(cache, solution, package, build, targetDirectory); } catch (Exception e) { @@ -103,7 +103,7 @@ static async Task ProcessToolManifest(SourceCacheContext cache, string manifest, Log.Information(" Updated in {Elapsed}", Formatter.FormatElapsed(stopwatch.Elapsed)); } -static async Task ProcessSolution(SourceCacheContext cache, string solution, string? package, bool build) +static async Task ProcessSolution(SourceCacheContext cache, string solution, string? package, bool build, string targetDirectory) { if (Excluder.ShouldExclude(solution)) { @@ -115,15 +115,15 @@ static async Task ProcessSolution(SourceCacheContext cache, string solution, str var solutionDirectory = Directory.GetParent(solution)!.FullName; - var props = Path.Combine(solutionDirectory, "Directory.Packages.props"); - if (!File.Exists(props)) + var propsLocation = FileSystem.FindPropsFile(solutionDirectory, targetDirectory); + if (propsLocation is null) { Log.Error(" Only central packages supported. Skipping: {Solution}", solution); return; } var stopwatch = Stopwatch.StartNew(); - await Updater.Update(cache, props, package); + await Updater.Update(cache, propsLocation, package); Log.Information(" Updated in {Elapsed}", Formatter.FormatElapsed(stopwatch.Elapsed)); if (build) @@ -131,4 +131,3 @@ static async Task ProcessSolution(SourceCacheContext cache, string solution, str await DotnetStarter.Build(solution); } } -