пʼятниця, 19 серпня 2011 р.

AsmDiff вер0.1

Известный в узких кругах Eugene Kirpichov написал в гугллоплюсе


Project to do when at the airport: .NET assembly diff tool. Read two folders of assemblies, report what's different. Should take a few hours and be very useful from the start - surprisingly there's no free tool to do that. I need to know what's really different (e.g. which methods have different code) and I'm not interested in a differing build timestamp or GUID.


У меня выдались свободных полчаса и тулзу я сделал.


На c# c Linq оно решается в один метод.

Code Snippet
  1. public static IEnumerable<DiffRecord> CecilAssebmlyDiff(AssemblyDefinition firstAssembly, AssemblyDefinition secondAssembly)
  2. {
  3.     var firstData = from module in firstAssembly.Modules
  4.                     from type in module.GetTypes()
  5.                     from method in type.Methods
  6.                     let parameters = method.Parameters
  7.                     let returnType = method.ReturnType
  8.  
  9.                     // for some system methods body can be null, so we should check it
  10.                     where method.HasBody
  11.                     let instructions = method.Body.Instructions
  12.  
  13.                     let code = method.SourceCode()
  14.                     let bytes = code
  15.                     select new { type, method, parameters, returnType, bytes };
  16.  
  17.     var secondData = from module in secondAssembly.Modules
  18.                      from type in module.GetTypes()
  19.                      from method in type.Methods
  20.                      let parameters = method.Parameters
  21.                      let returnType = method.ReturnType
  22.  
  23.                      // for some system methods body can be null, so we should check it
  24.                      where method.HasBody
  25.                      let instructions = method.Body.Instructions
  26.  
  27.                      let code = method.SourceCode()
  28.                      let bytes = code
  29.                      select new { type, method, parameters, returnType, bytes };
  30.  
  31.     var changedMethods = from firstMethod in firstData
  32.                          from secondMethod in secondData
  33.                          where
  34.                              // type names are the same
  35.                          firstMethod.type.FullName.Equals(secondMethod.type.FullName)
  36.                              // method names are the same
  37.                           && firstMethod.method.Name == secondMethod.method.Name
  38.                              // return typse are the same
  39.                           && firstMethod.returnType.FullName == secondMethod.returnType.FullName
  40.                              // parameters are the same
  41.                           && firstMethod.parameters.Except(secondMethod.parameters, x => x.ParameterType.FullName).Count() == 0
  42.                              //!!! dirty hack, byte arrays compared by their string representations
  43.                              // bodies ARE NOT the same
  44.                          && !firstMethod.bytes.Equals(secondMethod.bytes)
  45.  
  46.                          select new { firstMethod = firstMethod, secondMethod = secondMethod };


Собственно, ничего военного. Можно было бы вынести загрузку данных для различных сборок в отдельный метод, но лениво.

Результат работы выглядит следующим образом:
$ asmdiff first second
CoolLibrary.dllCoolLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullInt32 Test.Sample(x:String)
private int Sample(string x){return 66;}

CoolLibrary.dllCoolLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullInt32 Test.Sample(x:String)
private int Sample(string x){return 33;}

Архив с кодом на файлопомойке
В ближайшее время залью на какой-нибудь github.

Скачать сорцы и примеры можно здесь : проект на гитхабе

использовать просто "asmdiff folder1 folder2"

Зы. Рекурсивного обхода директорий нет.
ЗЫЫ. Обработки исключений тоже пока никакой.

Немає коментарів:

Дописати коментар