Внедрить хеш коммита git в dll .Net

103

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

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

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

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

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

Связанный с C ++ вопрос можно найти здесь .

EDIT

Per @ запрос mattanja, я хочу разместить скрипт мерзавец крючка я использую в своих проектах. Настройка:

  • Перехватчики - это сценарии оболочки Linux, которые находятся в папке : path_to_project \ .git \ hooks
  • Если вы используете msysgit , папка хуков уже содержит несколько примеров скриптов. Чтобы git вызывал их, удалите расширение .sample из имени скрипта.
  • Имена сценариев ловушек соответствуют событию, которое их вызывает. В моем случае я изменил пост-фиксацию и пост-слияние .
  • Мой файл AssemblyInfo.cs находится непосредственно по пути к проекту (на том же уровне, что и папка .git ). Он содержит 23 строки, и я использую git для создания 24-й.

Поскольку моя Linux-оболочка немного устарела, сценарий просто считывает первые 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

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

баваза
источник

Ответы:

64

Мы используем теги в 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:

введите описание изображения здесь

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

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

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

Ремесленник
источник
14
Привет, я хотел спросить месяц назад, но у меня не хватило репутации, чтобы прокомментировать. Когда вы говорите: «Наш процесс сборки помещает хэш git в атрибут AssemblyInformationalVersion в AssemblyInfo.cs», что именно там происходит? Вы просто создаете визуальную студию или используете что-то вроде NAnt или какой-то другой инструмент?
John Jesus
3
Мы используем рубин (рейк) для автоматизации нашей сборки. Одна из наших задач сборки rake обновляет файл CommonAssemblyInfo.cs, который используется во всех проектах в решении. Задача создает файл CommonAssemblyInfo.cs с помощью albacore - github.com/derickbailey/Albacore. Одним из значений AssemblyInfo, которые задает задача, является AssemblyInformationalVersion.
Handcraftsman
3
@John Jesus - как предложил Lazy Badger, вы также можете использовать git-хуки для изменения AssemblyInfo.cs после фиксации / слияния и т. Д. (Это то, что я в конечном итоге сделал). См. Kernel.org/pub/software/scm/git/docs/githooks.html
bavaza
К вашему сведению, Albacore переехал в новую хаб-организацию: github.com/Albacore/albacore
kornman00
5
Следующий проект https://github.com/jeromerg/NGitVersion предлагает полное решение для создания GlobalAssemblyInfo.*файлов во время компиляции для проектов C # и C ++: по умолчанию сгенерированная версия сборки содержит: хеш фиксации, флаг, сигнализирующий о локальных изменениях, и инкремент, подсчитывающий количество фиксации от корня репозитория до текущей фиксации.
jeromerg
78

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

Вот шаги:

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

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

  • В Build Events добавьте событие 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();
        }
    }
}
Иоанн Иисус
источник
9
Этот подход работает достаточно хорошо. Однако я использовал "git rev-parse --short HEAD".
Брайан Рейтер
3
А, хорошо. Я использовал "git describe", потому что это действительно интересно (для меня), когда у вас есть тег; информация о версии содержит тег плюс количество коммитов после применения тега; никогда раньше не видел ничего подобного в SCM.
Джон Хесус
7
Я использую git describe --dirty, который добавляет флаг, когда разработчики работают с грязным рабочим деревом.
paulmelnikow
2
@ TamásSzelei пространство имен проекта - TryGitDescribe. После того, как файл version.txt будет встроен в исполняемый файл / артефакт сборки, вам необходимо добавить пространство имен, чтобы получить его.
John Jesus
2
Спасибо за полное решение. В моем случае раньше GetEntryAssemblyсобиралась сборка. В любом случае вы можете позвонить, GetName().Nameчтобы избежать жесткого кодирования имени.
astrowalker
53

ОБНОВИТЬ:

С тех пор, как я изначально ответил на этот вопрос, все изменилось. Microsoft.NET.Sdk(То есть вы должны использовать проект СОК-стиль) теперь включает поддержку для добавления фиксации хэша как на сборочный информационную версию, а также метаданные NuGet пакета, если соблюдены некоторые условия:

  1. <SourceRevisionId>Должно быть определено свойство. Это можно сделать, добавив такую ​​цель:
<Target Name="InitializeSourceControlInformation" BeforeTargets="AddSourceRevisionToInformationalVersion">
    <Exec 
      Command="git describe --long --always --dirty --exclude=* --abbrev=8"
      ConsoleToMSBuild="True"
      IgnoreExitCode="False"
      >
      <Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/>
    </Exec>
  </Target>

Эта цель выполняет команду, которая будет установлена SourceRevisionIdкак сокращенный (8 символов) хэш. BeforeTargets заставляет это запускаться до создания информационной версии сборки.

  1. Чтобы включить хэш в метаданные пакета nuget, <RepositoryUrl>также необходимо определить.

  2. <SourceControlInformationFeatureSupported>свойство должно быть true, это заставляет задачу пакета nuget также получать SourceRevisionId.

Я бы посоветовал людям отказаться от использования пакета MSBuildGitHash, поскольку этот новый метод более понятен и согласован.

ОРИГИНАЛ:

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

Этот пакет nuget реализует «чистое» решение MSBuild. Если вы не хотите зависеть от пакета nuget, вы можете просто скопировать эти Targets в свой файл 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среды выполнения. В следующем коде показано, как это можно сделать, если AssemblyInfoкласс включен в ту же сборку.

using System.Linq;
using System.Reflection;

public static class AssemblyInfo
{
    /// <summary> Gets the git hash value from the assembly
    /// or null if it cannot be found. </summary>
    public static string GetGitHash()
    {
        var asm = typeof(AssemblyInfo).Assembly;
        var attrs = asm.GetCustomAttributes<AssemblyMetadataAttribute>();
        return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
    }
}

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

MarkPflug
источник
2
Это сработало отлично. Я установил пакет nuget и смог вытащить хеш git с помощью Assembly.GetExecutingAssembly(), а затем изучить сборку CustomAttributes .
Gavin H
1
Если бы это был мой вопрос, я бы принял этот ответ. Отличный материал.
Дрю Ноукс
1
@GavinH, как ты получил GitHash? Я вижу, что это значение существует, но есть ли какой-нибудь чистый метод для получения настраиваемого атрибута по имени? Похоже, мне нужно написать длинный запрос where-select CustomAttributes, спасибо.
Okan Kocyigit
1
@ocanal да - к сожалению, я не смог найти более чистого способа сделать это, чем читать CustomAttributes. Например, вот функция, которую я использую для извлечения хеш-строки: pastebin.com/nVKGLhJC
Gavin H
2
@danmiser Я понятия не имею, что такое UseMerge / SingleAssemblyName, поэтому не могу вам помочь. Создайте проблему на github.com/MarkPflug/MSBuildGitHash, и я могу взглянуть на нее (это не обещание).
MarkPflug
14

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

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

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

введите описание изображения здесь

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

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

на показанном снимке экрана я проверил NetRevisionTool.exe в папке External / bin

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

введите описание изображения здесь

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

Шмендрик
источник
Хеш фиксации для меня всегда заканчивается как 00000. Я думал, это потому, что у меня были незафиксированные изменения, но все равно. Есть идеи, почему?
Виктор
3
Проблема заключалась в том, что NetRevision не находила мой исполняемый файл git. Причина в том, что мы используем SourceTree, а git встроен в него. Решением было скопировать git.exe и libiconv-2.dll из% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin в папку, содержащую NetRevision.exe. Мне также пришлось изменить события следующим образом: Событие перед сборкой: cd $ (ProjectDir) Библиотеки NetRevisionTool.exe / patch $ (ProjectDir) Событие после сборки: cd $ (ProjectDir) Библиотеки NetRevisionTool.exe / restore $ (ProjectDir)
Виктор
Для справки в будущем URL-адрес репозитория проекта был изменен некоторое время назад на github.com/ygoe/NetRevisionTool . Дополнительная информация также доступна на unclassified.software/apps/netrevisiontool .
ygoe
14

Думаю, на этот вопрос стоит дать исчерпывающий пошаговый ответ. Стратегия здесь заключается в том, чтобы запустить сценарий PowerShell из событий перед сборкой, который принимает файл шаблона и генерирует файл AssemblyInfo.cs с включенной информацией о теге git + счетчике фиксации.

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

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

Шаг 2. Создайте сценарий PowerShell с именем 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.

Атилио Джобсон
источник
И не забудьте сделать ваши теги git совместимыми с версиями файлов: например, 1.2.3. Если у вас есть более сложные теги, вам придется разбирать только совместимые части
Атилио Джобсон
2
Вместо использования шаблона и gitignoring real AssemblyInfo.csможно изменить AssemblyInfo.csна месте, построить, а затем выполнить git reset AssemblyInfo.csдо последней зафиксированной версии. Так что в репо всегда будет AssemblyInfo.cs, с $..$заменой только на время сборки.
Куба Wyrostek 08
Это отлично сработало. Я закончил тем, что использовал git describe --match "v[0-9]*" --long --always --dirtyдля фильтрации определенных тегов (содержащих номер версии) и для указания, было ли рабочее дерево чистым.
packoman
Вы также должны изменить свой RegEx в сценарии PS:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
packoman
4

Теперь это очень просто с помощью .NET Revision Task для MSBuild и работы с Visual Studio 2019.

Просто установите пакет NuGet Unclassified.NetRevisionTask , а затем настройте нужную информацию в AssemblyInfo.csфайле, как описано в документации GitHub .

Если вам нужен только хеш последней фиксации (длина = 8):

[assembly: AssemblyInformationalVersion("1.0-{chash:8}")]

Создайте свой проект / решение, и у вас будет что-то вроде этого:

введите описание изображения здесь

krlzlx
источник
Чтобы настроить формат в приложении NET.core, добавьте PropertyGroupв файл .csproj, как показано в README github.com/ygoe/NetRevisionTask/blob/master/README.md
sc911
3

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

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

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

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

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

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

Маркус
источник
@Wint нет, не добавляйте сгенерированный AssemblyInfo.cs в git. Если вы это сделаете, будет невозможно сделать не грязную сборку: P
jokedst
3

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

Обновление: это устарело, так как Stamp.Fody больше не поддерживается

стог
источник
1
на странице github Stamp.Fody написано: «Этот проект больше не поддерживается». Включение его в мой проект подняло CA0052 и CA0055
sc911
2

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

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }
roh85
источник
1
  1. Надеюсь, вы знаете, как вызывать внешние программы и перехватывать вывод во время сборки.
  2. Надеюсь, вы знаете, как в рабочем каталоге git игнорировать неверсированные файлы.

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

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

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

  • некоторые делают сцену
  • в хуке после фиксации
  • в фильтре smudge, если вы выберете способ реализации smudge / clean filter
Ленивый барсук
источник
0

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

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

У меня есть git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"событие предварительной сборки в свойствах проекта. Добавление 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 + хеш в "ProductVersion".

jelinek.01
источник
0

Ссылаясь на другой ответ ( https://stackoverflow.com/a/44278482/4537127 ), я также использовал VersionInfo.ttтекстовый шаблон для создания AssemblyInformationalVersionбез AutoT4.

(По крайней мере, работает в моем приложении C # WPF)

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

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

1) Импортируйте цели преобразования текста и выполните преобразования шаблонов для запуска в каждой сборке: (Ссылка 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>

..И код C # для получения AssemblyInformationalVersion(Ссылка https://stackoverflow.com/a/7770189/4537127 )

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

        return attribute.InformationalVersion;
    }
}

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

VersionInfo.cs
git_version.txt
киммоли
источник
0

Другой способ - сгенерировать файл Version.cs на этапе предварительной сборки. Я исследовал это в небольшом экспериментальном проекте, который распечатывает текущий хеш фиксации.

Проект загружен на https://github.com/sashoalm/GitCommitHashPrinter .

Пакетный код, который создает файл Version.cs, следующий:

@echo off

echo "Writing Version.cs file..."

@rem Pushd/popd are used to temporarily cd to where the BAT file is.
pushd $(ProjectDir)

@rem Verify that the command succeeds (i.e. Git is installed and we are in the repo).
git rev-parse HEAD || exit 1

@rem Syntax for storing a command's output into a variable (see https://stackoverflow.com/a/2340018/492336).
@rem 'git rev-parse HEAD' returns the commit hash.
for /f %%i in ('git rev-parse HEAD') do set commitHash=%%i

@rem Syntax for printing multiline text to a file (see https://stackoverflow.com/a/23530712/492336).
(
echo namespace GitCommitHashPrinter
echo {
echo     class Version
echo     {
echo         public static string CommitHash { get; set; } = "%commitHash%";
echo     }
echo }
)>"Version.cs"

popd    
сашоальм
источник
0

Место

<Target Name="UpdateVersion" BeforeTargets="CoreCompile">
  <Exec Command="php &quot;$(SolutionDir)build.php&quot; $(SolutionDir) &quot;$(ProjectDir)Server.csproj&quot;" />
</Target>

в YOUR_PROJECT_NAME.csproj

<?php

function between(string $string, string $after, string $before, int $offset = 0) : string{
    return substr($string, $pos = strpos($string, $after, $offset) + strlen($after),
        strpos($string, $before, $pos) - $pos);
}

$pipes = [];
$proc = proc_open("git rev-parse --short HEAD", [
    0 => ["pipe", "r"],
    1 => ["pipe", "w"],
    2 => ["pipe", "w"]
], $pipes, $argv[1]);

if(is_resource($proc)){
    $rev = stream_get_contents($pipes[1]);
    proc_close($proc);
}

$manifest = file_get_contents($argv[2]);
$version = between($manifest, "<Version>", "</Version>");
$ver = explode("-", $version)[0] . "-" . trim($rev);
file_put_contents($argv[2], str_replace($version, $ver, $manifest));

echo "New version generated: $ver" . PHP_EOL;
PeratX
источник