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

Port Differ to console application #13

Merged
merged 3 commits into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 6 additions & 3 deletions .paket/Paket.Restore.targets
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
</PropertyGroup>

<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.174.2' ">
<PaketRestoreRequired>true</PaketRestoreRequired>
</PropertyGroup>

<!-- Do a global restore if required -->
<Exec Command='$(PaketBootStrapperCommand)' Condition="Exists('$(PaketBootStrapperExePath)') AND !(Exists('$(PaketExePath)'))" ContinueOnError="false" />
Expand All @@ -93,7 +96,7 @@
<PaketOriginalReferencesFilePath Condition=" !Exists('$(PaketOriginalReferencesFilePath)')">$(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references</PaketOriginalReferencesFilePath>
<!-- paket.references -->
<PaketOriginalReferencesFilePath Condition=" !Exists('$(PaketOriginalReferencesFilePath)')">$(MSBuildProjectDirectory)\paket.references</PaketOriginalReferencesFilePath>

<DoAllResolvedFilesExist>false</DoAllResolvedFilesExist>
<DoAllResolvedFilesExist Condition="Exists(%(PaketResolvedFilePaths.Identity))">true</DoAllResolvedFilesExist>
<PaketRestoreRequired>true</PaketRestoreRequired>
Expand Down Expand Up @@ -132,11 +135,11 @@
<Error Condition=" '$(DoAllResolvedFilesExist)' != 'true' AND '$(ResolveNuGetPackages)' != 'False' " Text="One Paket file '@(PaketResolvedFilePaths)' is missing while restoring $(MSBuildProjectFile). Please delete 'paket-files/paket.restore.cached' and call 'paket restore'." />

<!-- Step 4 forward all msbuild properties (PackageReference, DotNetCliToolReference) to msbuild -->
<ReadLinesFromFile Condition="'@(PaketResolvedFilePaths)' != ''" File="%(PaketResolvedFilePaths.Identity)" ><!--Condition="Exists('%(PaketResolvedFilePaths.Identity)')"-->
<ReadLinesFromFile Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketResolvedFilePaths)' != ''" File="%(PaketResolvedFilePaths.Identity)" >
<Output TaskParameter="Lines" ItemName="PaketReferencesFileLines"/>
</ReadLinesFromFile>

<ItemGroup Condition=" '@(PaketReferencesFileLines)' != '' " >
<ItemGroup Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketReferencesFileLines)' != '' " >
<PaketReferencesFileLinesInfo Include="@(PaketReferencesFileLines)" >
<PackageName>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])</PackageName>
<PackageVersion>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])</PackageVersion>
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,12 @@ Works with `.NET Core` and `.NET 4.6` and up.

Supports `dotnet xunit`, `dotnet test`, `xunit.console.runner` and tests will be runnable in your IDE through VSTest and jetBrains Rider.

### [Differ](src/Differ/README.md)

Compare and Diff assemblies from different sources e.g. assemblies, directories, GitHub commit, NuGet packages.
Useful for determining what changes are introduced across versions, and if any are _breaking_.

Outputs differences in XML, Markdown or AsciiDoc.



19 changes: 19 additions & 0 deletions src/Differ/AssemblyDiffPair.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.IO;
using JustAssembly.Core;

namespace Differ
{
public class AssemblyDiffPair
{
public AssemblyDiffPair(FileInfo first, FileInfo second)
{
First = first ?? throw new ArgumentNullException(nameof(first));
Second = second ?? throw new ArgumentNullException(nameof(second));
}

public FileInfo First { get; }
public FileInfo Second { get; }
public IDiffItem Diff { get; set; }
}
}
42 changes: 42 additions & 0 deletions src/Differ/Differ.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net462</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Options" Version="5.3.0.1" />
<PackageReference Include="NuGet.Frameworks" Version="4.8.0" />
<PackageReference Include="Proc" Version="0.3.7" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="lib" />
</ItemGroup>
<ItemGroup>
<Reference Include="JustAssembly.API, Version=0.0.0.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\JustAssembly.API.dll</HintPath>
</Reference>
<Reference Include="JustAssembly.Core, Version=2017.2.713.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\JustAssembly.Core.dll</HintPath>
</Reference>
<Reference Include="JustAssembly.Infrastructure, Version=2017.2.713.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\JustAssembly.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="JustDecompile.External.JustAssembly, Version=2017.2.705.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\JustDecompile.External.JustAssembly.dll</HintPath>
</Reference>
<Reference Include="JustDecompiler, Version=2017.2.705.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\JustDecompiler.dll</HintPath>
</Reference>
<Reference Include="Telerik.JustDecompile.Mono.Cecil, Version=2017.2.705.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\Telerik.JustDecompile.Mono.Cecil.dll</HintPath>
</Reference>
<Reference Include="Telerik.JustDecompile.Mono.Cecil.Mdb, Version=2017.2.705.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\Telerik.JustDecompile.Mono.Cecil.Mdb.dll</HintPath>
</Reference>
<Reference Include="Telerik.JustDecompile.Mono.Cecil.Pdb, Version=2017.2.705.1, Culture=neutral, PublicKeyToken=2b2cea67609c9510">
<HintPath>lib\Telerik.JustDecompile.Mono.Cecil.Pdb.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
87 changes: 87 additions & 0 deletions src/Differ/Exporters/AsciiDocExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using JustAssembly.Core;

namespace Differ.Exporters
{
public class AsciiDocExporter : IExporter
{
public string Format { get; } = "asciidoc";

public void Export(AssemblyDiffPair assemblyDiffPair, string outputPath)
{
// IDiffItem implementations are internal so parse from XML for now
var xml = assemblyDiffPair.Diff.ToXml();
var doc = XDocument.Parse(xml);
var name = assemblyDiffPair.First.Name;
using (var writer = new StreamWriter(Path.Combine(outputPath, Path.ChangeExtension(name, "asciidoc"))))
{
writer.WriteLine($"== Breaking changes for {Path.GetFileNameWithoutExtension(name)}");
writer.WriteLine();

foreach (var typeElement in doc.Descendants("Type"))
WriteTypeElement(writer, typeElement);
}
}

private void WriteTypeElement(StreamWriter writer, XElement typeElement)
{
var typeName = typeElement.Attribute("Name")?.Value;
var diffType = (DiffType) Enum.Parse(typeof(DiffType), typeElement.Attribute("DiffType").Value);

switch(diffType)
{
case DiffType.Deleted:
writer.WriteLine($"[float]{Environment.NewLine}=== `{typeName}` is deleted");
break;
case DiffType.Modified:
WriteMemberElements(writer, typeName, typeElement);
break;
case DiffType.New:
writer.WriteLine($"[float]{Environment.NewLine}=== `{typeName}` is added");
break;
default:
throw new ArgumentOutOfRangeException();
}
}

private void WriteMemberElements(StreamWriter writer, string typeName, XElement typeElement)
{
var memberElements = typeElement.Elements("Method").Concat(typeElement.Elements("Property"));

if (memberElements.Any())
writer.WriteLine($"[float]{Environment.NewLine}=== `{typeName}`");

foreach (var memberElement in memberElements)
{
var memberName = memberElement.Attribute("Name")?.Value;
if (!string.IsNullOrEmpty(memberName) && Enum.TryParse(typeElement.Attribute("DiffType")?.Value, out DiffType diffType))
{
switch (diffType)
{
case DiffType.Deleted:
writer.WriteLine($"[float]{Environment.NewLine}==== `{memberName}` is deleted");
break;
case DiffType.Modified:
var diffItem = memberElement.Descendants("DiffItem").FirstOrDefault();
if (diffItem != null)
{
writer.WriteLine($"[float]{Environment.NewLine}==== `{memberName}`");
writer.WriteLine(
Regex.Replace(diffItem.Value, "changed from (.*?) to (.*).", "changed from `$1` to `$2`."));
}
break;
case DiffType.New:
writer.WriteLine($"[float]{Environment.NewLine}==== `{memberName}` is added");
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
}
}
22 changes: 22 additions & 0 deletions src/Differ/Exporters/ExporterCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;

namespace Differ.Exporters
{
public class ExporterCollection : KeyedCollection<string, IExporter>
{
protected override string GetKeyForItem(IExporter item) => item.Format;

public ExporterCollection(params IExporter[] exporters)
{
if (exporters == null)
throw new ArgumentNullException(nameof(exporters));

foreach (var exporter in exporters)
this.Add(exporter);
}

public string SupportedFormats => string.Join(", ", this.Select(e => e.Format));
}
}
11 changes: 11 additions & 0 deletions src/Differ/Exporters/IExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using JustAssembly.Core;

namespace Differ.Exporters
{
public interface IExporter
{
string Format { get; }

void Export(AssemblyDiffPair assemblyDiffPair, string outputPath);
}
}
87 changes: 87 additions & 0 deletions src/Differ/Exporters/MarkdownExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using JustAssembly.Core;

namespace Differ.Exporters
{
public class MarkdownExporter : IExporter
{
public string Format { get; } = "markdown";

public void Export(AssemblyDiffPair assemblyDiffPair, string outputPath)
{
// IDiffItem implementations are internal so parse from XML for now
var xml = assemblyDiffPair.Diff.ToXml();
var doc = XDocument.Parse(xml);
var name = assemblyDiffPair.First.Name;
using (var writer = new StreamWriter(Path.Combine(outputPath, Path.ChangeExtension(name, "md"))))
{
writer.WriteLine($"# Breaking changes for {Path.GetFileNameWithoutExtension(name)}");
writer.WriteLine();

foreach (var typeElement in doc.Descendants("Type"))
WriteTypeElement(writer, typeElement);
}
}

private void WriteTypeElement(StreamWriter writer, XElement typeElement)
{
var typeName = typeElement.Attribute("Name")?.Value;
var diffType = (DiffType) Enum.Parse(typeof(DiffType), typeElement.Attribute("DiffType").Value);

switch(diffType)
{
case DiffType.Deleted:
writer.WriteLine($"## `{typeName}` is deleted");
break;
case DiffType.Modified:
WriteMemberElements(writer, typeName, typeElement);
break;
case DiffType.New:
writer.WriteLine($"## `{typeName}` is added");
break;
default:
throw new ArgumentOutOfRangeException();
}
}

private void WriteMemberElements(StreamWriter writer, string typeName, XElement typeElement)
{
var memberElements = typeElement.Elements("Method").Concat(typeElement.Elements("Property"));

if (memberElements.Any())
writer.WriteLine($"## `{typeName}`");

foreach (var memberElement in memberElements)
{
var memberName = memberElement.Attribute("Name")?.Value;
if (!string.IsNullOrEmpty(memberName) && Enum.TryParse(typeElement.Attribute("DiffType")?.Value, out DiffType diffType))
{
switch (diffType)
{
case DiffType.Deleted:
writer.WriteLine($"### `{memberName}` is deleted");
break;
case DiffType.Modified:
var diffItem = memberElement.Descendants("DiffItem").FirstOrDefault();
if (diffItem != null)
{
writer.WriteLine($"### `{memberName}`");
writer.WriteLine(
Regex.Replace(diffItem.Value, "changed from (.*?) to (.*).", "changed from `$1` to `$2`."));
}
break;
case DiffType.New:
writer.WriteLine($"### `{memberName}` is added");
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
}
}
17 changes: 17 additions & 0 deletions src/Differ/Exporters/XmlExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.IO;

namespace Differ.Exporters
{
public class XmlExporter : IExporter
{
public string Format { get; } = "xml";

public void Export(AssemblyDiffPair assemblyDiffPair, string outputPath)
{
var xml = assemblyDiffPair.Diff.ToXml();
using (var writer = new StreamWriter(Path.Combine(outputPath, Path.ChangeExtension(assemblyDiffPair.First.Name, "xml"))))
writer.Write(xml);
}
}
}
Loading