Skip to content
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
18 changes: 16 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
# Verify settings
root = true

# Verify settings
[*.{received,verified}.{json,txt,xml}]
charset = utf-8
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false
trim_trailing_whitespace = false


[*.cs]
end_of_line = crlf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

[*.sh]
end_of_line = lf
6 changes: 3 additions & 3 deletions src/ProjectDiff.Core/BuildGraph.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace ProjectDiff.Core;
namespace ProjectDiff.Core;

public sealed class BuildGraph
{
public required IReadOnlyCollection<BuildGraphProject> Projects { get; init; }
}

}
43 changes: 35 additions & 8 deletions src/ProjectDiff.Core/BuildGraphDiff.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Frozen;
using System.Collections.Frozen;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace ProjectDiff.Core;

Expand All @@ -7,10 +9,12 @@ public static class BuildGraphDiff
public static IEnumerable<DiffProject> Diff(
BuildGraph previous,
BuildGraph current,
IEnumerable<string> modifiedFiles
IEnumerable<string> modifiedFiles,
ILoggerFactory? loggerFactory = null
)
{
var instance = new GraphDiffInstance(current);
loggerFactory ??= NullLoggerFactory.Instance;
var instance = new GraphDiffInstance(current, loggerFactory.CreateLogger<GraphDiffInstance>());

return instance.Execute(previous, modifiedFiles.ToFrozenSet());
}
Expand All @@ -19,20 +23,24 @@ private sealed class GraphDiffInstance
{
private readonly BuildGraph _graph;
private readonly Dictionary<string, bool> _modifiedProjects;
private readonly ILogger<GraphDiffInstance> _logger;

public GraphDiffInstance(BuildGraph graph)
public GraphDiffInstance(BuildGraph graph, ILogger<GraphDiffInstance> logger)
{
_modifiedProjects = new Dictionary<string, bool>(graph.Projects.Count);
_graph = graph;
_logger = logger;
}

public IEnumerable<DiffProject> Execute(BuildGraph previous, FrozenSet<string> modifiedFiles)
{
foreach (var currentProject in _graph.Projects)
{
var previousProject = previous.Projects.FirstOrDefault(it => it.Matches(currentProject));
using var scope = _logger.BeginScope(currentProject.FullPath);
var previousProject = previous.Projects.FirstOrDefault(it => it.FullPath == currentProject.FullPath);
if (previousProject is null)
{
_logger.LogDebug("Project not found in previous graph, marking as added");
yield return new DiffProject
{
Path = currentProject.FullPath,
Expand All @@ -42,6 +50,7 @@ public IEnumerable<DiffProject> Execute(BuildGraph previous, FrozenSet<string> m
}
else if (HasProjectChanged(previousProject, currentProject, modifiedFiles))
{
_logger.LogDebug("Project has changed, marking as modified");
yield return new DiffProject
{
Path = currentProject.FullPath,
Expand All @@ -51,6 +60,7 @@ public IEnumerable<DiffProject> Execute(BuildGraph previous, FrozenSet<string> m
}
else if (HasProjectReferencesChanged(previousProject, currentProject, modifiedFiles))
{
_logger.LogDebug("Project references have changed, marking as reference changed");
yield return new DiffProject
{
Path = currentProject.FullPath,
Expand All @@ -62,9 +72,10 @@ public IEnumerable<DiffProject> Execute(BuildGraph previous, FrozenSet<string> m

foreach (var previousProject in previous.Projects)
{
var existsInCurrent = _graph.Projects.Any(it => it.Matches(previousProject));
var existsInCurrent = _graph.Projects.Any(it => it.FullPath == previousProject.FullPath);
if (!existsInCurrent)
{
_logger.LogDebug("Project {Path} not found in current graph, marking as removed", previousProject.FullPath);
yield return new DiffProject
{
Path = previousProject.FullPath,
Expand Down Expand Up @@ -96,26 +107,33 @@ FrozenSet<string> modifiedFiles
return false;
}

private static bool HasProjectInputFilesChanged(
private bool HasProjectInputFilesChanged(
IReadOnlyCollection<string> previous,
IReadOnlyCollection<string> current,
FrozenSet<string> modifiedFiles
)
{
if (previous.Count != current.Count)
{
_logger.LogDebug(
"Input files count changed: {PreviousCount} -> {CurrentCount}",
previous.Count,
current.Count
);
return true;
}

foreach (var file in current)
{
if (!previous.Contains(file))
{
_logger.LogInformation("Input file {File} added", file);
return true;
}

if (modifiedFiles.Contains(file))
{
_logger.LogInformation("Input file {File} modified", file);
return true;
}
}
Expand All @@ -124,6 +142,7 @@ FrozenSet<string> modifiedFiles
{
if (!current.Contains(file))
{
_logger.LogInformation("Input file {File} removed", file);
return true;
}
}
Expand All @@ -140,13 +159,19 @@ FrozenSet<string> modifiedFiles
{
if (previous.References.Count != current.References.Count)
{
_logger.LogDebug(
"References count changed: {PreviousCount} -> {CurrentCount}",
previous.References.Count,
current.References.Count
);
return true;
}

foreach (var reference in current.References)
{
if (!previous.References.Contains(reference))
{
_logger.LogInformation("Reference {Reference} added", reference);
return true;
}

Expand All @@ -155,6 +180,7 @@ FrozenSet<string> modifiedFiles

if (HasProjectChanged(previousReference, currentReference, modifiedFiles))
{
_logger.LogInformation("Referenced project {Reference} modified", reference);
return true;
}
}
Expand All @@ -163,11 +189,12 @@ FrozenSet<string> modifiedFiles
{
if (!current.References.Contains(reference))
{
_logger.LogInformation("Referenced project {Reference} removed", reference);
return true;
}
}

return false;
}
}
}
}
41 changes: 32 additions & 9 deletions src/ProjectDiff.Core/BuildGraphFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Diagnostics;
using LibGit2Sharp;
using Microsoft.Build.Execution;
using Microsoft.Build.Graph;
using Microsoft.Build.Prediction;
Expand All @@ -10,21 +11,22 @@ public static class BuildGraphFactory
{
private static readonly IProjectGraphPredictor[] ProjectGraphPredictors = ProjectPredictors
.AllProjectGraphPredictors
// We create the build graph ourselves, we don't want referenced csproj files to be part of the input files
.Where(it => it is not ProjectFileAndImportsGraphPredictor)
.ToArray();


public static BuildGraph CreateForProjectGraph(
ProjectGraph graph,
IReadOnlyCollection<string> changedFiles
Repository repository,
IReadOnlyCollection<FileInfo> ignoredFiles
)
{
var executor = new ProjectGraphPredictionExecutor(
ProjectGraphPredictors,
ProjectPredictors.AllProjectPredictors
);

var collector = new BuildGraphPredictionCollector(graph, changedFiles);
var collector = new BuildGraphPredictionCollector(graph, repository, ignoredFiles);

executor.PredictInputsAndOutputs(graph, collector);

Expand All @@ -34,13 +36,19 @@ IReadOnlyCollection<string> changedFiles
private sealed class BuildGraphPredictionCollector : IProjectPredictionCollector
{
private readonly ProjectGraph _projectGraph;
private readonly Repository _repository;
private readonly IReadOnlyCollection<FileInfo> _ignoredFiles;
private readonly Dictionary<string, BuildGraphProjectCollector> _collectors;
private readonly IReadOnlyCollection<string> _changedFiles;

public BuildGraphPredictionCollector(ProjectGraph projectGraph, IReadOnlyCollection<string> changedFiles)
public BuildGraphPredictionCollector(
ProjectGraph projectGraph,
Repository repository,
IReadOnlyCollection<FileInfo> ignoredFiles
)
{
_projectGraph = projectGraph;
_changedFiles = changedFiles;
_repository = repository;
_ignoredFiles = ignoredFiles;
_collectors = new Dictionary<string, BuildGraphProjectCollector>(_projectGraph.ProjectNodes.Count);
foreach (var node in _projectGraph.ProjectNodes)
{
Expand All @@ -51,14 +59,29 @@ public BuildGraphPredictionCollector(ProjectGraph projectGraph, IReadOnlyCollect
}
}


public void AddInputFile(string path, ProjectInstance projectInstance, string predictorName)
{
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(path, projectInstance.Directory);
}

if (!_changedFiles.Contains(path))
// Only include files that are part of this repository
if (!path.StartsWith(_repository.Info.WorkingDirectory))
{
return;
}

// Ignore files that are in the ignored files list
if (_ignoredFiles.Count > 0 && _ignoredFiles.Any(it => it.FullName == path))
{
return;
}

// Ignore any files that are ignored by .gitignore
var relativePath = Path.GetRelativePath(_repository.Info.WorkingDirectory, path).Replace('\\', '/');
if (_repository.Ignore.IsPathIgnored(relativePath))
{
return;
}
Expand Down Expand Up @@ -152,4 +175,4 @@ public BuildGraphProject ToBuildGraphProject()
}
}
}
}
}
9 changes: 2 additions & 7 deletions src/ProjectDiff.Core/BuildGraphProject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ProjectDiff.Core;
namespace ProjectDiff.Core;

public sealed class BuildGraphProject
{
Expand All @@ -16,9 +16,4 @@ IReadOnlyCollection<string> references
public string FullPath { get; }
public IReadOnlyCollection<string> InputFiles { get; }
public IReadOnlyCollection<string> References { get; }

public bool Matches(BuildGraphProject other)
{
return FullPath == other.FullPath;
}
}
}
8 changes: 4 additions & 4 deletions src/ProjectDiff.Core/DiffProject.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
namespace ProjectDiff.Core;
namespace ProjectDiff.Core;

public sealed record DiffProject
{
public required string Path { get; init; }
public string Name => System.IO.Path.GetFileNameWithoutExtension(Path);
public required DiffStatus Status { get; init; }



public required IReadOnlyCollection<string> ReferencedProjects { get; init; } = [];
}
}
4 changes: 2 additions & 2 deletions src/ProjectDiff.Core/DiffStatus.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
namespace ProjectDiff.Core;
namespace ProjectDiff.Core;

public enum DiffStatus
{
Added,
Removed,
Modified,
ReferenceChanged,
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
using Microsoft.Build.FileSystem;
using Microsoft.Build.FileSystem;
using Microsoft.Build.Graph;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace ProjectDiff.Core.Entrypoints;

public sealed class DirectoryScanEntrypointProvider : IEntrypointProvider
{
private readonly ILogger<DirectoryScanEntrypointProvider> _logger;

public DirectoryScanEntrypointProvider(ILogger<DirectoryScanEntrypointProvider> logger)

public DirectoryScanEntrypointProvider(ILogger<DirectoryScanEntrypointProvider>? logger = null)
{
_logger = logger;
_logger = logger ?? NullLogger<DirectoryScanEntrypointProvider>.Instance;
}

public Task<IEnumerable<ProjectGraphEntryPoint>> GetEntrypoints(
Expand All @@ -26,4 +28,4 @@ CancellationToken cancellationToken

return Task.FromResult(entrypoints);
}
}
}
4 changes: 2 additions & 2 deletions src/ProjectDiff.Core/Entrypoints/IEntrypointProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Build.FileSystem;
using Microsoft.Build.FileSystem;
using Microsoft.Build.Graph;

namespace ProjectDiff.Core.Entrypoints;
Expand All @@ -10,4 +10,4 @@ Task<IEnumerable<ProjectGraphEntryPoint>> GetEntrypoints(
MSBuildFileSystemBase fs,
CancellationToken cancellationToken
);
}
}
Loading
Loading