Change Output format to match PR feedback

Don't use Environment.Exit()

PR Feedback, Unecessary Usings and Immutable types
This commit is contained in:
Bryan 2015-12-15 18:09:08 -08:00
parent dd5c0bb423
commit 3b848c0487
9 changed files with 169 additions and 56 deletions

View file

@ -120,8 +120,8 @@ header "Testing stage2 End to End ..."
DOTNET_HOME=$STAGE2_DIR DOTNET_TOOLS=$STAGE2_DIR $DIR/test/e2e-test.sh DOTNET_HOME=$STAGE2_DIR DOTNET_TOOLS=$STAGE2_DIR $DIR/test/e2e-test.sh
# Run Validation for Project.json dependencies # Run Validation for Project.json dependencies
dotnet publish "$REPOROOT/tools/MultiProjectValidator" -o "$OUTPUT_DIR/../tools" dotnet publish "$REPOROOT/tools/MultiProjectValidator" -o "$STAGE2_DIR/../tools"
#TODO for release builds this should fail #TODO for release builds this should fail
set +e set +e
"$OUTPUT_DIR/tools/pjvalidate" "$REPOROOT/src" "$STAGE2_DIR/../tools/pjvalidate" "$REPOROOT/src"
set -e set -e

View file

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MultiProjectValidator namespace MultiProjectValidator
{ {

View file

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
namespace ProjectSanity.AnalysisRules.DependencyMismatch
{
internal class DependencyGroup
{
public static DependencyGroup CreateWithEntry(DependencyInfo dependencyInfo)
{
var dependencyGroup = new DependencyGroup
{
DependencyName = dependencyInfo.Name,
VersionDependencyInfoMap = new Dictionary<string, List<DependencyInfo>>()
};
dependencyGroup.AddEntry(dependencyInfo);
return dependencyGroup;
}
public string DependencyName { get; private set; }
public Dictionary<string, List<DependencyInfo>> VersionDependencyInfoMap { get; private set; }
public bool HasConflict
{
get
{
return VersionDependencyInfoMap.Count > 1;
}
}
public void AddEntry(DependencyInfo dependencyInfo)
{
if (!dependencyInfo.Name.Equals(DependencyName, StringComparison.OrdinalIgnoreCase))
{
throw new Exception("Added dependency does not match group");
}
if (VersionDependencyInfoMap.ContainsKey(dependencyInfo.Version))
{
VersionDependencyInfoMap[dependencyInfo.Version].Add(dependencyInfo);
}
else
{
VersionDependencyInfoMap[dependencyInfo.Version] = new List<DependencyInfo>()
{
dependencyInfo
};
}
}
}
}

View file

@ -0,0 +1,21 @@
using Microsoft.DotNet.ProjectModel;
namespace ProjectSanity.AnalysisRules.DependencyMismatch
{
internal class DependencyInfo
{
public static DependencyInfo Create(ProjectContext context, LibraryDescription library)
{
return new DependencyInfo
{
ProjectPath = context.ProjectFile.ProjectFilePath,
Version = library.Identity.Version.ToString(),
Name = library.Identity.Name
};
}
public string ProjectPath { get; private set; }
public string Version { get; private set; }
public string Name { get; private set; }
}
}

View file

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using System.Text;
using ProjectSanity.AnalysisRules.DependencyMismatch;
namespace MultiProjectValidator.AnalysisRules namespace MultiProjectValidator.AnalysisRules
{ {
@ -12,62 +13,73 @@ namespace MultiProjectValidator.AnalysisRules
{ {
var targetGroupedContexts = GroupContextsByTarget(projectContexts); var targetGroupedContexts = GroupContextsByTarget(projectContexts);
var failureMessages = EvaluateTargetContextGroups(targetGroupedContexts); var failureMessages = EvaluateProjectContextTargetGroups(targetGroupedContexts);
var pass = failureMessages.Count == 0; var pass = failureMessages.Count == 0;
var result = new AnalysisResult(failureMessages, pass); var result = new AnalysisResult(failureMessages, pass);
return result; return result;
} }
private List<string> EvaluateTargetContextGroups(Dictionary<string, List<ProjectContext>> targetGroupedContexts) private List<string> EvaluateProjectContextTargetGroups(Dictionary<string, List<ProjectContext>> targetGroupedProjectContexts)
{ {
var failureMessages = new List<string>(); var failureMessages = new List<string>();
foreach (var target in targetGroupedContexts.Keys) foreach (var target in targetGroupedProjectContexts.Keys)
{ {
var targetContexts = targetGroupedContexts[target]; var targetProjectContextGroup = targetGroupedProjectContexts[target];
failureMessages.AddRange(EvaluateTargetContextGroup(targetContexts)); var groupFailureMessages = EvaluateProjectContextTargetGroup(targetProjectContextGroup);
if (groupFailureMessages.Count > 0)
{
string aggregateFailureMessage = $"Failures for Target {target} {Environment.NewLine}{Environment.NewLine}"
+ string.Join("", groupFailureMessages);
failureMessages.Add(aggregateFailureMessage);
}
} }
return failureMessages; return failureMessages;
} }
private List<string> EvaluateTargetContextGroup(List<ProjectContext> targetContexts) private List<string> EvaluateProjectContextTargetGroup(List<ProjectContext> targetProjectContextGroup)
{ {
var failedMessages = new List<string>(); var failedMessages = new List<string>();
var assemblyVersionMap = new Dictionary<string, string>();
foreach(var context in targetContexts) var dependencyGroups = CreateDependencyGroups(targetProjectContextGroup);
foreach (var dependencyGroup in dependencyGroups)
{ {
var libraries = context.LibraryManager.GetLibraries(); if(dependencyGroup.HasConflict)
foreach(var library in libraries)
{ {
var name = library.Identity.Name; failedMessages.Add(GetDependencyGroupConflictMessage(dependencyGroup));
var version = library.Identity.Version.ToString();
if (assemblyVersionMap.ContainsKey(name))
{
var existingVersion = assemblyVersionMap[name];
if (!string.Equals(existingVersion, version, StringComparison.OrdinalIgnoreCase))
{
string message =
$"Dependency mismatch in {context.ProjectFile.ProjectFilePath} for dependency {name}. Versions {version}, {existingVersion}";
failedMessages.Add(message);
}
}
else
{
assemblyVersionMap[name] = version;
}
} }
} }
return failedMessages; return failedMessages;
} }
private string GetDependencyGroupConflictMessage(DependencyGroup dependencyGroup)
{
StringBuilder sb = new StringBuilder();
sb.Append($"Conflict for {dependencyGroup.DependencyName} in projects:{Environment.NewLine}");
foreach (var version in dependencyGroup.VersionDependencyInfoMap.Keys)
{
var dependencyInfoList = dependencyGroup.VersionDependencyInfoMap[version];
foreach (var dependencyInfo in dependencyInfoList)
{
sb.Append($"Version: {dependencyInfo.Version} Path: {dependencyInfo.ProjectPath} {Environment.NewLine}");
}
}
sb.Append(Environment.NewLine);
return sb.ToString();
}
private Dictionary<string, List<ProjectContext>> GroupContextsByTarget(List<ProjectContext> projectContexts) private Dictionary<string, List<ProjectContext>> GroupContextsByTarget(List<ProjectContext> projectContexts)
{ {
var targetContextMap = new Dictionary<string, List<ProjectContext>>(); var targetContextMap = new Dictionary<string, List<ProjectContext>>();
@ -90,5 +102,39 @@ namespace MultiProjectValidator.AnalysisRules
return targetContextMap; return targetContextMap;
} }
private List<DependencyGroup> CreateDependencyGroups(List<ProjectContext> projectContexts)
{
var libraryNameDependencyGroupMap = new Dictionary<string, DependencyGroup>();
foreach (var projectContext in projectContexts)
{
var libraries = projectContext.LibraryManager.GetLibraries();
foreach (var library in libraries)
{
var dependencyInfo = DependencyInfo.Create(projectContext, library);
if (libraryNameDependencyGroupMap.ContainsKey(dependencyInfo.Name))
{
var dependencyGroup = libraryNameDependencyGroupMap[dependencyInfo.Name];
dependencyGroup.AddEntry(dependencyInfo);
}
else
{
var dependencyGroup = DependencyGroup.CreateWithEntry(dependencyInfo);
libraryNameDependencyGroupMap[dependencyInfo.Name] = dependencyGroup;
}
}
}
return libraryNameDependencyGroupMap.Values.ToList();
}
} }
} }

View file

@ -1,7 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
namespace MultiProjectValidator namespace MultiProjectValidator

View file

@ -10,7 +10,17 @@ namespace MultiProjectValidator
{ {
public static int Main(string[] args) public static int Main(string[] args)
{ {
var rootPath = ParseAndValidateArgs(args);
string rootPath = null;
try
{
rootPath = ParseAndValidateArgs(args);
}
catch
{
return 1;
}
List<ProjectContext> projects = null; List<ProjectContext> projects = null;
try try
@ -20,7 +30,7 @@ namespace MultiProjectValidator
catch(Exception e) catch(Exception e)
{ {
Console.WriteLine("Failed to load projects from path: " + rootPath); Console.WriteLine("Failed to load projects from path: " + rootPath);
Exit(1); return 1;
} }
var analyzer = ProjectAnalyzer.Create(projects); var analyzer = ProjectAnalyzer.Create(projects);
@ -80,7 +90,7 @@ namespace MultiProjectValidator
if (args.Length != 1) if (args.Length != 1)
{ {
PrintHelp(); PrintHelp();
Exit(1); throw new Exception();
} }
string rootPath = args[0]; string rootPath = args[0];
@ -88,16 +98,11 @@ namespace MultiProjectValidator
if (!Directory.Exists(rootPath)) if (!Directory.Exists(rootPath))
{ {
Console.WriteLine("Root Directory does not exist: " + rootPath); Console.WriteLine("Root Directory does not exist: " + rootPath);
Exit(1); throw new Exception();
} }
return rootPath; return rootPath;
} }
private static void Exit(int code)
{
Environment.Exit(code);
}
private static void PrintHelp() private static void PrintHelp()
{ {

View file

@ -1,7 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using MultiProjectValidator.AnalysisRules; using MultiProjectValidator.AnalysisRules;

View file

@ -1,8 +1,5 @@
using System; using System.IO;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
namespace MultiProjectValidator namespace MultiProjectValidator