Подтвердить что ты не робот

Вставить git commit hash в .Net dll

Я создаю приложение С#, используя Git как мой контроль версий.

Есть ли способ автоматически вставлять последний хеш фиксации в исполняемый файл при создании моего приложения?

Например, печать хэша commit на консоли будет выглядеть примерно так:

class PrintCommitHash
{
    private String lastCommitHash = ?? // What do I put here?
    static void Main(string[] args)
    {
        // Display the version number:
        System.Console.WriteLine(lastCommitHash );
    }
}

Обратите внимание, что это нужно делать в строить время, а не время выполнения, так как мой развернутый исполняемый файл не будет иметь доступ к репозиторию Git.

Соответствующий вопрос для С++ можно найти здесь .

ИЗМЕНИТЬ

По запросу @mattanja я отправляю Git hook script, который я использую в своих проектах. Настройка:

  • Крючки - это скрипты linux shell, которые помещаются под: path_to_project \.git\hooks
  • Если вы используете msysgit, папка hooks уже содержит некоторые примеры скриптов. Чтобы сделать их Git, удалите расширение ".sample" из имени script.
  • Имена скриптов hook совпадают с вызывающим их событием. В моем случае я модифицировал post-commit и post-merge.
  • Мой файл AssemblyInfo.cs находится непосредственно под контуром проекта (тот же уровень, что и папка .git). Он содержит 23 строки, и я использую Git для генерации 24-го.

Поскольку мой linux-обход немного ржавый, script просто считывает первые 23 строки AssemblyInfo.cs во временный файл, эхо-хэш хеша Git до последней строки и переименовывает файл обратно в AssemblyInfo.cs. Я уверен, что есть лучшие способы сделать это:

#!/bin/sh
cmt=$(git rev-list --max-count=1 HEAD)
head -23 AssemblyInfo.cs > AssemblyInfo.cs.tmp
echo [assembly: AssemblyFileVersion\(\"$cmt\"\)] >> AssemblyInfo.cs.tmp
mv AssemblyInfo.cs.tmp AssemblyInfo.cs

Надеюсь, что это поможет.

4b9b3361

Ответ 1

Мы используем теги в git для отслеживания версий.

git tag -a v13.3.1 -m "version 13.3.1"

Вы можете получить версию с хешем из git через:

git describe --long

Наш процесс сборки помещает хэш git в атрибут AssemblyInformationalVersion файла AssemblyInfo.cs:

[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]

После компиляции вы можете просмотреть версию из обозревателя Windows:

enter image description here

Вы также можете получить его программно через:

var build = ((AssemblyInformationalVersionAttribute)Assembly
  .GetAssembly(typeof(YOURTYPE))
  .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
  .InformationalVersion;

где YOURTYPE - это любой тип в сборке с атрибутом AssemblyInformationalVersion.

Ответ 2

Вы можете вставить файл version.txt в исполняемый файл, а затем прочитать version.txt из исполняемого файла. Чтобы создать файл version.txt, используйте git describe --long

Вот шаги:

Используйте событие Build для вызова git

  • Щелкните правой кнопкой мыши проект и выберите "Свойства"

  • В событиях сборки добавьте событие Pre-Build, содержащее (обратите внимание на кавычки):

    "C:\Program Files\ Git\bin\git.exe" описать -long > "$ (ProjectDir)\version.txt"

    Это создаст файл version.txt в каталоге проекта.

Вставить файл version.txt в исполняемый файл

  • Щелкните правой кнопкой мыши по проекту и выберите Добавить существующий элемент
  • Добавьте файл version.txt (измените фильтр выбора файлов, чтобы увидеть все файлы)
  • После добавления version.txt щелкните его правой кнопкой мыши в обозревателе решений и выберите "Свойства"
  • Изменение действия сборки для встроенного ресурса
  • Сменить копию на каталог вывода для копирования всегда
  • Добавьте version.txt в файл .gitignore

Прочитайте строку версии встроенного текстового файла

Вот пример кода для чтения строки версии встроенного текстового файла:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace TryGitDescribe
{
    class Program
    {
        static void Main(string[] args)
        {
            string gitVersion= String.Empty;
            using (Stream stream = Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("TryGitDescribe." + "version.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                gitVersion= reader.ReadToEnd();
            }

            Console.WriteLine("Version: {0}", gitVersion);
            Console.WriteLine("Hit any key to continue");
            Console.ReadKey();
        }
    }
}

Ответ 3

Другой способ сделать это - использовать NetRevisionTool с помощью встроенной магии Visual Studio. Я продемонстрирую это здесь для Visual Studio 2013 Professional Edition, но это будет работать и с другими версиями.

Итак, сначала загрузите NetRevisionTool. Вы включаете NetRevisionTool.exe в свой PATH или проверяете его в своем репозитории и создаете предварительную сборку визуальной студии и действие после сборки и меняете AssemblyInfo.cs.

Примером, который добавит ваш git -hash в AssemblyInformationVersion, будет следующее: В настройках вашего проекта:

enter image description here

в AssemblyInfo.cs вашего проекта вы меняете/добавляете строку:

[сборка: AssemblyInformationalVersion ( "1.1. {dmin: 2015}. {chash: 6} {!} - {branch}" )]

в показанном скриншоте, который я проверил в NetRevisionTool.exe в папке External/bin

После сборки, если вы затем щелкните правой кнопкой мыши свой двоичный файл и перейдите к свойствам, вы увидите следующее:

enter image description here

Надеюсь, это поможет кому-то там.

Ответ 4

Я думаю, что этот вопрос стоит дать полный пошаговый ответ. Стратегия здесь - запустить powershell script из событий предварительной сборки, которые принимают файл шаблона и генерирует файл AssemblyInfo.cs с включенной меткой git. +/.

Шаг 1: создайте файл AssemblyInfo_template.cs в папке Project\Properties на основе вашего исходного AssemblyInfo.cs, но содержащий:

[assembly: AssemblyVersion("$FILEVERSION$")]
[assembly: AssemblyFileVersion("$FILEVERSION$")]
[assembly: AssemblyInformationalVersion("$INFOVERSION$")]

Шаг 2: Создайте файл powershell script с именем InjectGitVersion.ps1, источником которого является

# InjectGitVersion.ps1
#
# Set the version in the projects AssemblyInfo.cs file
#


# Get version info from Git. example 1.2.3-45-g6789abc
$gitVersion = git describe --long --always;

# Parse Git version info into semantic pieces
$gitVersion -match '(.*)-(\d+)-[g](\w+)$';
$gitTag = $Matches[1];
$gitCount = $Matches[2];
$gitSHA1 = $Matches[3];

# Define file variables
$assemblyFile = $args[0] + "\Properties\AssemblyInfo.cs";
$templateFile =  $args[0] + "\Properties\AssemblyInfo_template.cs";

# Read template file, overwrite place holders with git version info
$newAssemblyContent = Get-Content $templateFile |
    %{$_ -replace '\$FILEVERSION\$', ($gitTag + "." + $gitCount) } |
    %{$_ -replace '\$INFOVERSION\$', ($gitTag + "." + $gitCount + "-" + $gitSHA1) };

# Write AssemblyInfo.cs file only if there are changes
If (-not (Test-Path $assemblyFile) -or ((Compare-Object (Get-Content $assemblyFile) $newAssemblyContent))) {
    echo "Injecting Git Version Info to AssemblyInfo.cs"
    $newAssemblyContent > $assemblyFile;       
}

Шаг 3: Сохраните файл InjectGitVersion.ps1 в каталоге решений в папке BuildScripts

Шаг 4: Добавьте следующую строку в проект. События Pre-Build

powershell -ExecutionPolicy ByPass -File  $(SolutionDir)\BuildScripts\InjectGitVersion.ps1 $(ProjectDir)

Шаг 5: Создайте свой проект.

Шаг 6: При необходимости добавьте AssemblyInfo.cs в свой файл git ignore

Ответ 5

Я создал простой пакет nuget, который вы можете включить в свой проект, который позаботится об этом для вас: https://www.nuget.org/packages/MSBuildGitHash/

Этот пакет nuget реализует "чистое" решение MSBuild. Если вы предпочитаете не зависеть от пакета nuget, вы можете просто скопировать эти целевые объекты в ваш файл csproj, и он должен включать хэш git в качестве настраиваемого атрибута сборки:

<Target Name="GetGitHash" BeforeTargets="WriteGitHash" Condition="'$(BuildHash)' == ''">
  <PropertyGroup>
    <!-- temp file for the git version (lives in "obj" folder)-->
    <VerFile>$(IntermediateOutputPath)gitver</VerFile>
  </PropertyGroup>

  <!-- write the hash to the temp file.-->
  <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(VerFile)" />

  <!-- read the version into the GitVersion itemGroup-->
  <ReadLinesFromFile File="$(VerFile)">
    <Output TaskParameter="Lines" ItemName="GitVersion" />
  </ReadLinesFromFile>
  <!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
  <PropertyGroup>
    <BuildHash>@(GitVersion)</BuildHash>
  </PropertyGroup>    
</Target>

<Target Name="WriteGitHash" BeforeTargets="CoreCompile">
  <!-- names the obj/.../CustomAssemblyInfo.cs file -->
  <PropertyGroup>
    <CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
  </PropertyGroup>
  <!-- includes the CustomAssemblyInfo for compilation into your project -->
  <ItemGroup>
    <Compile Include="$(CustomAssemblyInfoFile)" />
  </ItemGroup>
  <!-- defines the AssemblyMetadata attribute that will be written -->
  <ItemGroup>
    <AssemblyAttributes Include="AssemblyMetadata">
      <_Parameter1>GitHash</_Parameter1>
      <_Parameter2>$(BuildHash)</_Parameter2>
    </AssemblyAttributes>
  </ItemGroup>
  <!-- writes the attribute to the customAssemblyInfo file -->
  <WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
</Target>

Здесь есть две цели. Первый, "GetGitHash", загружает хэш git в свойство MSBuild с именем BuildHash, он делает это только в том случае, если BuildHash еще не определен. Это позволяет передать его в MSBuild в командной строке, если хотите. Вы можете передать его в MSBuild следующим образом:

MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL

Вторая цель, "WriteGitHash", напишет хэш-значение для файла во временной папке "obj" с именем "CustomAssemblyInfo.cs". Этот файл будет содержать строку, которая выглядит так:

[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]

Этот файл CustomAssemblyInfo.cs будет скомпилирован в вашу сборку, поэтому вы можете использовать отражение для поиска AssemblyMetadata во время выполнения.

Некоторые преимущества этого дизайна заключаются в том, что он не касается каких-либо файлов в папке проекта, все мутированные файлы находятся в папке "obj". Ваш проект также будет построен идентично из Visual Studio или из командной строки. Он также может быть легко настроен для вашего проекта и будет контролироваться исходным кодом вместе с вашим файлом csproj.

Ответ 6

Поскольку в другом ответе уже упоминается бит git, после того, как у вас есть SHA, вы можете подумать о создании файла AssemblyInfo.cs вашего проекта в предварительном сборке.

Один из способов сделать это - создать файл шаблона AssemblyInfo.cs.tmpl, с помощью заполнителя для вашего SHA, например $$ GITSHA $$, например.

[assembly: AssemblyDescription("$$GITSHA$$")]

Затем вы должны заменить этот заполнитель и вывести файл AssemblyInfo.cs для компилятора С#.

Чтобы узнать, как это можно сделать с помощью SubWCRev для SVN, см. этот ответ. Не должно быть трудно сделать что-то подобное для git.

Другими способами может быть "этап выполнения", как упомянуто, т.е. написать задачу MSBuild, которая делает что-то подобное. Еще один способ - как-то обработать DLL (ildasm + ilasm say), но я думаю, что упомянутые выше варианты, вероятно, самые простые.

Ответ 7

Для полностью автоматизированного и гибкого метода проверки https://github.com/Fody/Stamp. Мы успешно использовали это для наших проектов Git (а также эта версия для проектов SVN)

Ответ 8

Вы можете использовать однострочный файл powershell для обновления всех файлов assemblyinfo с помощью хэша commit.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }

Ответ 9

Я использую комбинацию принятого ответа и небольшого дополнения. У меня установлено расширение AutoT4 (https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4), чтобы повторно запустить шаблоны перед сборкой.

получение версии от GIT

У меня есть git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt" в событии pre-build в свойствах проекта. Добавление git_version.txt и VersionInfo.cs в .gitignore - неплохая идея.

версия внедрения в метаданных

Я добавил в проект шаблон VersionInfo.tt:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

<#
if (File.Exists(Host.ResolvePath("git_version.txt")))
{
    Write("[assembly: AssemblyInformationalVersion(\""+ File.ReadAllText(Host.ResolvePath("git_version.txt")).Trim() + "\")]");
}else{
    Write("// version file not found in " + Host.ResolvePath("git_version.txt"));
}

#>

Теперь у меня есть тег git tag + hash в "ProductVersion".

Ответ 10

Ссылаясь на другой ответ (fooobar.com/questions/106463/...), я также использовал текстовый шаблон VersionInfo.tt для генерации AssemblyInformationalVersion без AutoT4.

(Atleast работает в моем приложении WPF на С#)

Проблема заключалась в том, что события Pre-build выполнялись после трансформаций шаблонов, поэтому после клонирования, файл git_version.txt не был там, и сборка завершилась неудачей. После его создания вручную, чтобы преобразование прошло один раз, оно было обновлено после преобразования и всегда было одним фиксатором.

Мне пришлось внести две корректировки в файл .csproj(это применимо, по крайней мере, для сообщества Visual Studio 2017)

1) Импортируйте цели трансформации текста и создайте преобразования шаблонов для каждой сборки: (Ref https://msdn.microsoft.com/en-us/library/ee847423.aspx)

<PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <TransformOnBuild>true</TransformOnBuild>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

и после <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />

2) Запустите git describe перед трансформацией шаблона (так что git_version.txt существует, когда VersionInfo.tt преобразуется):

<Target Name="PreBuild" BeforeTargets="ExecuteTransformations">
  <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(ProjectDir)git_version.txt" />
</Target>

.. И код С#, чтобы получить AssemblyInformationalVersion (Ref fooobar.com/questions/106468/...)

public string AppGitHash
{
    get
    {
        AssemblyInformationalVersionAttribute attribute = (AssemblyInformationalVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false).FirstOrDefault();

        return attribute.InformationalVersion;
    }
}

.. И добавьте сгенерированные файлы в .gitignore

VersionInfo.cs
git_version.txt

Ответ 11

  • Надеюсь, вы знаете, как вызывать внешние программы и перехватывать выходные данные во время сборки.
  • Надеюсь, вы знаете, как в рабочем каталоге git игнорировать неверсированные файлы.

Как отмечено в @learath2, вывод git rev-parse HEAD даст вам простой хеш.

Если вы используете теги в Git -repository (и используете теги, не более ли описательные и читаемые, чем git rev-parse), вывод может быть получен от git describe (в то же время успешно используется позже в git checkout)

Вы можете вызвать rev-parse | описать в:

  • некоторые стадии выполнения
  • в цепочке после фиксации
  • в smudge filter, если вы выберете smudge/clean filters способ реализации