Osadź skrót git commit w dll .Net

102

Buduję aplikację C #, używając Git jako mojej kontroli wersji.

Czy istnieje sposób na automatyczne osadzenie ostatniego skrótu zatwierdzenia w pliku wykonywalnym podczas kompilowania aplikacji?

Na przykład wypisanie skrótu zatwierdzenia do konsoli wyglądałoby mniej więcej tak:

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

Należy pamiętać, że należy to zrobić w czasie kompilacji , a nie w czasie wykonywania , ponieważ mój wdrożony plik wykonywalny nie będzie miał dostępu do repozytorium git.

Powiązane pytanie dotyczące C ++ można znaleźć tutaj .

EDYTUJ

Żądanie @ mattanja, wysyłam skrypt git hook, którego używam w moich projektach. Ustawić:

  • Punkty zaczepienia to skrypty powłoki systemu Linux, które są umieszczone w: ścieżka_do_projektu \ .git \ hooks
  • Jeśli używasz msysgit , folder hooks zawiera już kilka przykładowych skryptów. Aby wywołać je git, usuń rozszerzenie „.sample” z nazwy skryptu.
  • Nazwy skryptów przechwytujących odpowiadają zdarzeniu, które je wywołuje. W moim przypadku zmodyfikowałem post-commit i post-merge .
  • Mój plik AssemblyInfo.cs znajduje się bezpośrednio pod ścieżką projektu (na tym samym poziomie co folder .git ). Zawiera 23 linie, a do wygenerowania 24 używam gita.

Ponieważ mój Linux-shelling jest nieco zardzewiały, skrypt po prostu wczytuje pierwsze 23 wiersze AssemblyInfo.cs do pliku tymczasowego, wyświetla echo skrótu git do ostatniej linii i zmienia nazwę pliku z powrotem na AssemblyInfo.cs . Jestem pewien, że istnieją lepsze sposoby na zrobienie tego:

#!/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

Mam nadzieję że to pomoże.

bavaza
źródło

Odpowiedzi:

64

Używamy tagów w git do śledzenia wersji.

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

Możesz pobrać wersję z hashem z git przez:

git describe --long

Nasz proces kompilacji umieszcza skrót git w atrybucie AssemblyInformationalVersion pliku AssemblyInfo.cs:

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

Po kompilacji możesz wyświetlić wersję w eksploratorze Windows:

wprowadź opis obrazu tutaj

Możesz również uzyskać to programowo przez:

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

gdzie YOURTYPE jest dowolnym typem w zestawie, który ma atrybut AssemblyInformationalVersion.

Rzemieślnik
źródło
14
Cześć, chciałem zapytać miesiąc temu, ale nie miałem wystarczającej liczby przedstawicieli, aby komentować. Kiedy mówisz: „Nasz proces kompilacji umieszcza skrót git w atrybucie AssemblyInformationalVersion obiektu AssemblyInfo.cs”, co dokładnie się tam dzieje? Czy po prostu tworzysz wersję Visual Studio, czy też używasz czegoś w rodzaju NAnt lub innego narzędzia?
John Jesus,
3
Używamy ruby ​​(rake) do automatyzacji naszej kompilacji. Jedno z naszych zadań kompilacji rake aktualizuje plik CommonAssemblyInfo.cs, który jest używany we wszystkich projektach w rozwiązaniu. Zadanie generuje plik CommonAssemblyInfo.cs przy użyciu albacore - github.com/derickbailey/Albacore Jedną z wartości AssemblyInfo, które ustawia zadanie, jest AssemblyInformationalVersion.
Rzemieślnik
3
@John Jesus - jak zasugerował Lazy Badger, możesz również użyć haków git do zmiany AssemblyInfo.cs po zatwierdzeniu / scaleniu itp. (To właśnie zrobiłem). Zobacz kernel.org/pub/software/scm/git/docs/githooks.html
bavaza
Do Twojej wiadomości, Albacore przeniosło się do nowej organizacji centralnej: github.com/Albacore/albacore
kornman00
5
Poniższy projekt https://github.com/jeromerg/NGitVersion oferuje kompletne rozwiązanie do generowania GlobalAssemblyInfo.*plików w czasie kompilacji dla projektów C # i C ++: Domyślnie wygenerowana wersja zestawu zawiera: skrót zatwierdzenia, flagę sygnalizującą lokalne zmiany oraz przyrost zliczający ilość zatwierdzenia z katalogu głównego repozytorium do bieżącego zatwierdzenia.
jeromerg
78

Możesz osadzić plik version.txt w pliku wykonywalnym, a następnie odczytać plik version.txt z pliku wykonywalnego. Aby utworzyć plik version.txt , użyjgit describe --long

Oto kroki:

Użyj zdarzenia kompilacji, aby zadzwonić do gita

  • Kliknij projekt prawym przyciskiem myszy i wybierz Właściwości

  • W Zdarzeniach kompilacji dodaj zdarzenie przed kompilacją zawierające (zwróć uwagę na cudzysłowy):

    „C: \ Program Files \ Git \ bin \ git.exe” opisać --long> „$ (ProjectDir) \ version.txt”

    Spowoduje to utworzenie pliku version.txt w katalogu projektu.

Osadź wersję.txt w pliku wykonywalnym

  • Kliknij prawym przyciskiem myszy projekt i wybierz Dodaj istniejący element
  • Dodaj plik version.txt (zmień filtr wyboru plików, aby zobaczyć wszystkie pliki)
  • Po dodaniu version.txt kliknij go prawym przyciskiem myszy w Eksploratorze rozwiązań i wybierz Właściwości
  • Zmień akcję kompilacji na zasób osadzony
  • Zmień opcję Kopiuj na katalog wyjściowy, aby zawsze kopiować
  • Dodaj wersję.txt do pliku .gitignore

Przeczytaj informację o wersji osadzonego pliku tekstowego

Oto przykładowy kod do odczytywania ciągu wersji osadzonego pliku tekstowego:

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();
        }
    }
}
Jana Jezusa
źródło
9
To podejście działa dość dobrze. Jednak użyłem "git rev-parse --short HEAD".
Brian Reiter
3
Ach, dobrze. Użyłem „git opis”, ponieważ jest to naprawdę interesujące (dla mnie), gdy masz tag; informacja o wersji zawiera tag oraz liczbę zatwierdzeń po zastosowaniu tagu; nigdy wcześniej nie widziałem czegoś takiego jak w SCM.
Jan Jezus
7
Używam git describe --dirty, co dodaje flagę, gdy programiści pracują z brudnym drzewem roboczym.
paulmelnikow
2
@ TamásSzelei przestrzeń nazw projektu to TryGitDescribe. Gdy plik version.txt zostanie osadzony w artefakcie pliku wykonywalnego / zespołu, należy dodać na początku przestrzeń nazw, aby go usunąć.
John Jesus,
2
Dziękuję za kompletne rozwiązanie. W moim przypadku GetEntryAssemblydostawałem montaż. W każdym razie możesz zadzwonić, GetName().Nameaby uniknąć zakodowania nazwy na stałe.
astrowalker
52

AKTUALIZACJA:

Rzeczy uległy zmianie, odkąd pierwotnie odpowiedziałem na to pytanie. Microsoft.NET.Sdk(Czyli należy używać projekt SDK-style) zawiera teraz wsparcie dla dodanie popełnić hash zarówno wersję montaż informacyjną, jak również metadanych pakietu Nuget, jeśli spełnione są pewne warunki:

  1. <SourceRevisionId>Właściwość musi być określona. Można to zrobić, dodając taki cel:
<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>

Ten cel wykonuje polecenie, które ustawi SourceRevisionId jako skrócony (8-znakowy) skrót. BeforeTargets powoduje, że zostanie to uruchomione przed utworzeniem wersji informacyjnej zestawu.

  1. Aby uwzględnić skrót w metadanych pakietu NuGet, <RepositoryUrl>należy również zdefiniować plik.

  2. <SourceControlInformationFeatureSupported>musi być true, powoduje to, że zadanie pakietu NuGet pobiera również SourceRvisionId.

Odciągnąłbym ludzi od korzystania z pakietu MSBuildGitHash, ponieważ ta nowa technika jest czystsza i najbardziej spójna.

ORYGINALNY:

Stworzyłem prosty pakiet nuget, który możesz dołączyć do swojego projektu, który zajmie się tym za Ciebie: https://www.nuget.org/packages/MSBuildGitHash/

Ten pakiet NuGet implementuje „czyste” rozwiązanie MSBuild. Jeśli wolisz nie polegać na pakiecie nuget, możesz po prostu skopiować te elementy docelowe do pliku csproj i powinny one zawierać skrót git jako atrybut zestawu niestandardowego:

<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>

Są tu dwa cele. Pierwsza z nich, „GetGitHash”, ładuje skrót git do właściwości programu MSBuild o nazwie BuildHash, robi to tylko wtedy, gdy BuildHash nie jest jeszcze zdefiniowany. Dzięki temu możesz przekazać go do programu MSBuild w wierszu polecenia, jeśli wolisz. Możesz przekazać to do MSBuild w następujący sposób:

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

Drugi cel, „WriteGitHash”, zapisze wartość skrótu do pliku w tymczasowym folderze „obj” o nazwie „CustomAssemblyInfo.cs”. Ten plik będzie zawierał linię, która wygląda następująco:

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

Ten plik CustomAssemblyInfo.cs zostanie skompilowany do zestawu, dzięki czemu można użyć odbicia, aby wyszukać plik AssemblyMetadataw czasie wykonywania. Poniższy kod pokazuje, jak można to zrobić, gdy AssemblyInfoklasa jest uwzględniona w tym samym zestawie.

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;
    }
}

Niektóre zalety tego projektu to to, że nie zmienia on żadnych plików w folderze projektu, wszystkie zmutowane pliki znajdują się w folderze „obj”. Twój projekt będzie również kompilowany identycznie z poziomu programu Visual Studio lub z wiersza polecenia. Można go również łatwo dostosować do projektu i będzie on kontrolowany wraz z plikiem csproj.

MarkPflug
źródło
2
To działało doskonale. Zainstalowałem pakiet nuget i udało mi się wyciągnąć skrót git za pomocą Assembly.GetExecutingAssembly(), a następnie zbadałem zestaw CustomAttributes .
Gavin H,
1
Gdyby to było moje pytanie, przyjąłbym tę odpowiedź. Świetne rzeczy.
Drew Noakes
1
@GavinH, jak dostałeś GitHash? Widzę, że ta wartość istnieje, ale czy istnieje czysta metoda uzyskania atrybutu niestandardowego według nazwy? Wygląda na to, że muszę napisać długie zapytanie gdzie-wybierz CustomAttributes, dzięki.
Okan Kocyigit,
1
@ocanal tak - niestety nie mogłem znaleźć lepszego sposobu na zrobienie tego niż przeczytanie CustomAttributes. Na przykład tutaj jest funkcja, której używam do wyodrębnienia ciągu skrótu: pastebin.com/nVKGLhJC
Gavin H
2
@danmiser Nie mam pojęcia, co to jest „UseMerge / SingleAssemblyName”, więc nie mogę Ci pomóc. Utwórz problem na github.com/MarkPflug/MSBuildGitHash, a ja mogę się temu przyjrzeć (to nie jest obietnica).
MarkPflug
14

Innym sposobem, aby to zrobić, jest użycie narzędzia NetRVisionTool z pewną magią wbudowanego programu Visual Studio. Przedstawię to tutaj dla Visual Studio 2013 Professional Edition, ale będzie to działać również z innymi wersjami.

Więc najpierw pobierz NetRvisionTool. Uwzględniasz NetRvisionTool.exe w PATH lub wpisujesz go do repozytorium i tworzysz prekompilację programu Visual Studio i akcję po kompilacji oraz zmieniasz plik AssemblyInfo.cs.

Przykładem, który dodałby twój git-hash do twojego AssemblyInformationVersion, byłby następujący: W ustawieniach projektu:

wprowadź opis obrazu tutaj

w AssemblyInfo.cs twojego projektu zmieniasz / dodajesz linię:

[assembly: AssemblyInformationalVersion ("1.1. {dmin: 2015}. {chash: 6} {!} - {branch}")]

na pokazanym zrzucie ekranu sprawdziłem w NetRvisionTool.exe w folderze External / bin

Po kompilacji, jeśli następnie klikniesz prawym przyciskiem myszy plik binarny i przejdziesz do właściwości, powinieneś zobaczyć coś takiego:

wprowadź opis obrazu tutaj

Mam nadzieję, że to komuś pomoże

schmendrick
źródło
Wartość skrótu dla mnie zawsze kończy się na 00000. Myślałem, że dzieje się tak, ponieważ miałem niezatwierdzone zmiany, ale wciąż to samo. Każdy pomysł, dlaczego?
Viktor
3
Problem polegał na tym, że NetRvision nie znajdował mojego pliku wykonywalnego git. Powodem jest to, że używamy SourceTree, a git jest z nim osadzony. Rozwiązaniem było skopiowanie git.exe i libiconv-2.dll z% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin do folderu zawierającego NetRvision.exe. Musiałem również zmodyfikować zdarzenia w ten sposób: Zdarzenie przed kompilacją: cd $ (ProjectDir) Biblioteki NetRvisionTool.exe / patch $ (ProjectDir) Zdarzenie po kompilacji: cd $ (ProjectDir) Biblioteki NetRvisionTool.exe / restore $ (ProjectDir)
Viktor
Na przyszłość, URL repozytorium projektu zmienił się jakiś czas temu na github.com/ygoe/NetRvisionTool . Więcej informacji jest również dostępnych na unclassified.software/apps/netrevisiontool .
ygoe
14

Myślę, że na to pytanie warto udzielić pełnej odpowiedzi krok po kroku. Strategia w tym miejscu polega na uruchomieniu skryptu PowerShell ze zdarzeń przed kompilacją, które pobierają plik szablonu i generują plik AssemblyInfo.cs z tagiem git + dołączonymi informacjami o liczbie zatwierdzeń.

Krok 1: utwórz plik AssemblyInfo_template.cs w folderze Project \ Properties, na podstawie oryginalnego pliku AssemblyInfo.cs, ale zawierający:

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

Krok 2: Utwórz skrypt PowerShell o nazwie InjectGitVersion.ps1, którego źródłem jest:

# 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;       
}

Krok 3: Zapisz plik InjectGitVersion.ps1 w katalogu rozwiązania w folderze BuildScripts

Krok 4: Dodaj następujący wiersz do wydarzeń przed kompilacją projektu

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

Krok 5: Zbuduj swój projekt.

Krok 6: Opcjonalnie dodaj AssemblyInfo.cs do pliku ignorowania git

Atilio Jobson
źródło
Pamiętaj też, aby zapewnić zgodność tagów git z wersjami plików: na przykład 1.2.3. Jeśli masz bardziej skomplikowane tagi, będziesz musiał przeanalizować tylko kompatybilne części
Atilio Jobson
2
Zamiast używać szablonu i prawdziwego gitignorowania, AssemblyInfo.csmożna modyfikować AssemblyInfo.csw miejscu, budować, a następnie resetować git AssemblyInfo.csdo ostatniej zatwierdzonej wersji. Czyli w repozytorium zawsze będzie AssemblyInfo.cs, z $..$podstawieniem tylko na czas kompilacji.
Kuba Wyrostek
To działało świetnie. Skończyło się na tym, że użyłem git describe --match "v[0-9]*" --long --always --dirtydo filtrowania określonych tagów (zawierających numer wersji) i do wskazywania, czy drzewo robocze jest czyste.
packoman
Musisz także zmodyfikować swoje RegEx w skrypcie PS:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
packoman
4

Teraz jest to bardzo łatwe zadaniu .NET Revision Task dla MSBuild i pracy z programem Visual Studio 2019.

Po prostu zainstaluj Nuget pakiet Unclassified.NetRevisionTask , a następnie skonfigurować żądane informacje w AssemblyInfo.cspliku w sposób opisany w dokumentacji GitHub .

Jeśli chcesz tylko hash ostatniego zatwierdzenia (długość = 8):

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

Zbuduj swój projekt / rozwiązanie, a będziesz miał coś takiego:

wprowadź opis obrazu tutaj

krlzlx
źródło
Aby skonfigurować format w aplikacji NET.core, dodaj PropertyGroupdo pliku .csproj , jak widać w pliku README github.com/ygoe/NetRvdTask/blob/master/README.md
sc911
3

Ponieważ druga odpowiedź już wspomina bit git, kiedy już masz SHA, możesz rozważyć wygenerowanie AssemblyInfo.cspliku projektu w haku przed kompilacją.

Jednym ze sposobów jest utworzenie AssemblyInfo.cs.tmplpliku szablonu z elementem zastępczym dla twojego SHA, np. $$ GITSHA $$, np.

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

Następnie hak przed kompilacją musi zastąpić ten symbol zastępczy i wyprowadzić plik AssemblyInfo.cs, aby kompilator C # mógł go pobrać.

Aby zobaczyć, jak można to zrobić za pomocą SubWCRev dla SVN, zobacz tę odpowiedź . Nie powinno być trudno zrobić coś podobnego dla gita.

Innymi sposobami byłoby „tworzenie etapu”, jak wspomniano, tj. Napisanie zadania MSBuild, które robi coś podobnego. Jeszcze innym sposobem może być jakoś przetworzenie biblioteki DLL (powiedzmy ildasm + ilasm), ale myślę, że opcje wymienione powyżej są prawdopodobnie najłatwiejsze.

Marcus
źródło
@Wint nie, nie dodawaj wygenerowanego AssemblyInfo.cs do git. Jeśli to zrobisz, nie będzie można zrobić nie
brudzącej
3

Aby uzyskać w pełni zautomatyzowaną i elastyczną metodę płatności, https://github.com/Fody/Stamp . Z powodzeniem wykorzystaliśmy to w naszych projektach Git (a także w tej wersji dla projektów SVN)

Aktualizacja: To jest nieaktualne, ponieważ Stamp.Fody nie jest już utrzymywane

mamuesstack
źródło
1
na stronie github Stamp.Fody jest napisane: „Ten projekt nie jest już obsługiwany.”. Włączenie go do mojego projektu podniosło CA0052 i CA0055
sc911
2

Możesz użyć jednowierszowego programu PowerShell, aby zaktualizować wszystkie pliki informacji o zespole za pomocą skrótu zatwierdzenia.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }
roh85
źródło
1
  1. Mam nadzieję, że wiesz, jak wywoływać programy zewnętrzne i przechwytywać dane wyjściowe w czasie kompilacji.
  2. Mam nadzieję, że wiesz, jak w katalogu roboczym git zignorować niewersjonowane pliki.

Jak zauważył @ learath2, wynik polecenia git rev-parse HEADda ci zwykły hash.

Jeśli używasz tagów w repozytorium Git (i używasz tagów, czy nie jest to bardziej opisowe i czytelne niż git rev-parse), dane wyjściowe mogą być odbierane z git describe(chociaż również z powodzeniem używane później git checkout)

Możesz wywołać rev-parse | opisać w:

  • niektórzy robią scenę
  • w haku po zatwierdzeniu
  • w smudge filter, jeśli wybierzesz sposób implementacji smudge / clean filter
Lazy Badger
źródło
0

Używam kombinacji zaakceptowanej odpowiedzi i małego dodatku. Mam zainstalowane rozszerzenie AutoT4 ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ), aby ponownie uruchomić szablony przed kompilacją.

pobieranie wersji z GIT

Mam git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"w moim zdarzeniu przed kompilacją we właściwościach projektu. Dodanie git_version.txt i VersionInfo.cs do .gitignore to całkiem niezły pomysł.

osadzanie wersji w metadanych

Dodałem VersionInfo.ttszablon do mojego projektu:

<#@ 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"));
}

#>

Teraz mam swój tag git + hash w „ProductVersion”.

jelinek.01
źródło
0

Odnosząc się do innej odpowiedzi ( https://stackoverflow.com/a/44278482/4537127 ) wykorzystałem również VersionInfo.ttszablon tekstowy do wygenerowaniaAssemblyInformationalVersion bez AutoT4.

(Atleast działa w mojej aplikacji C # WPF)

Problem polegał na tym, że zdarzenia przed kompilacją były uruchamiane po transformacji szablonu, więc po sklonowaniu git_version.txtpliku nie było i kompilacja kończyła się niepowodzeniem. Po utworzeniu go ręcznie, aby umożliwić jednokrotne przejście transformacji, był aktualizowany po transformacji i zawsze pozostawał za jednym zatwierdzeniem .

Musiałem dokonać dwóch zmian w pliku .csproj (dotyczy to przynajmniej Visual Studio Community 2017)

1) Zaimportuj cele transformacji tekstu i wykonaj transformacje szablonów, które będą uruchamiane w każdej kompilacji: (patrz 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>

oraz po <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

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

2) Wykonaj git describeprzebieg przed transformacją szablonu (tak, aby git_version.txtbył tam, kiedy VersionInfo.ttjest transformowany):

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

.. I kod C #, aby uzyskać AssemblyInformationalVersion(patrz https://stackoverflow.com/a/7770189/4537127 )

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

        return attribute.InformationalVersion;
    }
}

..I dodaj wygenerowane pliki do .gitignore

VersionInfo.cs
git_version.txt
kimmoli
źródło
0

Innym sposobem byłoby wygenerowanie pliku Version.cs z etapu przed kompilacją. Zbadałem to w małym projekcie weryfikującym koncepcję, który wypisuje bieżący skrót zatwierdzenia.

Projekt jest załadowany na https://github.com/sashoalm/GitCommitHashPrinter .

Kod wsadowy, który tworzy plik Version.cs, to:

@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    
sashoalm
źródło
0

Miejsce

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

w 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
źródło