Incorpora l'hash git commit in una DLL .Net


102

Sto costruendo un'applicazione C #, usando Git come controllo della versione.

C'è un modo per incorporare automaticamente l'ultimo hash di commit nell'eseguibile quando creo la mia applicazione?

Ad esempio, la stampa dell'hash del commit sulla console sarebbe simile a:

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

Si noti che questo deve essere fatto in fase di compilazione , non in fase di esecuzione , poiché il mio eseguibile distribuito non avrà il repository git accessibile.

Una domanda correlata per C ++ può essere trovata qui .

MODIFICA

Per richiesta di @ mattanja, sto postando lo script git hook che uso nei miei progetti. Il set up:

  • Gli hook sono script della shell di Linux, che si trovano sotto: path_to_project \ .git \ hooks
  • Se stai usando msysgit , la cartella hooks contiene già alcuni script di esempio. Per fare in modo che git li chiami, rimuovi l'estensione ".sample" dal nome dello script.
  • I nomi degli script hook corrispondono all'evento che li richiama. Nel mio caso, ho modificato post-commit e post-merge .
  • Il mio file AssemblyInfo.cs si trova direttamente nel percorso del progetto (stesso livello della cartella .git ). Contiene 23 righe e io uso git per generare il 24.

Dato che il mio shell di Linux è un po 'arrugginito, lo script legge semplicemente le prime 23 righe di AssemblyInfo.cs in un file temporaneo, riporta l'hash git sull'ultima riga e rinomina il file in AssemblyInfo.cs . Sono sicuro che ci sono modi migliori per farlo:

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

Spero che questo ti aiuti.

Risposte:


64

Usiamo i tag in git per tenere traccia delle versioni.

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

Puoi ottenere la versione con hash da git tramite:

git describe --long

Il nostro processo di compilazione inserisce l'hash git nell'attributo AssemblyInformationalVersion del file AssemblyInfo.cs:

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

Una volta compilato, puoi visualizzare la versione da Windows Explorer:

inserisci qui la descrizione dell'immagine

Puoi anche ottenerlo in modo programmatico tramite:

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

dove YOURTYPE è qualsiasi tipo nell'assembly con l'attributo AssemblyInformationalVersion.


14
Ciao, volevo chiedere un mese fa, ma non avevo abbastanza rappresentante per commentare. Quando dici "Il nostro processo di compilazione inserisce l'hash git nell'attributo AssemblyInformationalVersion di AssemblyInfo.cs", cosa sta succedendo esattamente lì? Stai solo costruendo uno studio visivo o stai usando qualcosa come NAnt o qualche altro strumento?
John Jesus

3
Usiamo ruby ​​(rake) per automatizzare la nostra build. Una delle nostre attività di compilazione rake aggiorna il file CommonAssemblyInfo.cs utilizzato in tutti i progetti nella soluzione. L'attività genera il file CommonAssemblyInfo.cs utilizzando albacore - github.com/derickbailey/Albacore Uno dei valori AssemblyInfo impostati dall'attività è AssemblyInformationalVersion.
Handcraftsman

3
@ John Jesus - come suggerito da Lazy Badger, puoi anche usare git hooks per cambiare AssemblyInfo.cs dopo commit / merge ecc (questo è quello che ho finito per fare). Vedi kernel.org/pub/software/scm/git/docs/githooks.html
bavaza

Cordiali saluti, Albacore si è trasferito in una nuova organizzazione hub: github.com/Albacore/albacore
kornman00

5
Il seguente progetto https://github.com/jeromerg/NGitVersion offre una soluzione completa per generare GlobalAssemblyInfo.*file in fase di compilazione per progetti C # e C ++: per impostazione predefinita, la versione dell'assembly generata contiene: l'hash del commit, un flag che segnala le modifiche locali e un incremento contando la quantità di commit dalla radice del repository al commit corrente.
Jeromerg

78

Puoi incorporare un file version.txt nell'eseguibile e quindi leggere il file version.txt dall'eseguibile. Per creare il file version.txt , usagit describe --long

Ecco i passaggi:

Usa un evento Build per chiamare git

  • Fare clic con il tasto destro sul progetto e selezionare Proprietà

  • In Build Events, aggiungi un evento di pre-compilazione contenente (nota le virgolette):

    "C: \ Programmi \ Git \ bin \ git.exe" descrive --long> "$ (ProjectDir) \ version.txt"

    Ciò creerà un file version.txt nella directory del progetto.

Incorpora version.txt nell'eseguibile

  • Fare clic con il tasto destro sul progetto e selezionare Aggiungi elemento esistente
  • Aggiungi il file version.txt (cambia il filtro di selezione file per farti vedere tutti i file)
  • Dopo aver aggiunto version.txt , fare clic con il pulsante destro del mouse su di esso in Esplora soluzioni e selezionare Proprietà
  • Modificare l'azione di compilazione in Risorsa incorporata
  • Cambia Copia nella directory di output in Copia sempre
  • Aggiungi version.txt al tuo file .gitignore

Leggere la stringa della versione del file di testo incorporato

Ecco un po 'di codice di esempio per leggere la stringa della versione del file di testo incorporato:

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
Questo approccio funziona abbastanza bene. Ho usato "git rev-parse --short HEAD", però.
Brian Reiter

3
Ah bene. Ho usato "git description" perché è davvero interessante (per me) quando hai un tag; le informazioni sulla versione hanno il tag più il numero di commit dopo che il tag è stato applicato; mai visto qualcosa di simile in un SCM prima.
John Jesus

7
Uso git describe --dirty, che aggiunge un flag quando gli sviluppatori stanno lavorando con un albero funzionante sporco.
paulmelnikow

2
@ TamásSzelei lo spazio dei nomi del progetto è TryGitDescribe. Dopo che il file version.txt è stato incorporato nell'artefatto eseguibile / assembly, è necessario anteporre lo spazio dei nomi per estrarlo.
John Jesus

2
Grazie per la soluzione completa. Nel mio caso ho usato GetEntryAssemblyper ottenere l'assemblaggio. In ogni caso puoi chiamare GetName().Nameper evitare di codificare il nome.
astrowalker

52

AGGIORNARE:

Le cose si sono evolute da quando ho originariamente risposto a questa domanda. Microsoft.NET.Sdk( Il che significa che devi utilizzare un progetto in stile sdk) ora include il supporto per l'aggiunta dell'hash del commit sia alla versione informativa dell'assembly che ai metadati del pacchetto nuget, se vengono soddisfatte alcune condizioni:

  1. La <SourceRevisionId>proprietà deve essere definita. Questo può essere fatto aggiungendo un obiettivo come questo:
<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>

Questa destinazione esegue un comando che verrà impostato SourceRevisionIdcome hash abbreviato (8 caratteri). BeforeTargets fa sì che ciò venga eseguito prima della creazione della versione informativa dell'assembly.

  1. Per includere l'hash nei metadati del pacchetto nuget, è <RepositoryUrl>necessario definire anche il.

  2. <SourceControlInformationFeatureSupported>deve essere true, questo fa sì che l'attività del pacchetto nuget raccolga anche SourceRevisionId.

Vorrei allontanare le persone dall'usare il pacchetto MSBuildGitHash, poiché questa nuova tecnica è più pulita e coerente.

ORIGINALE:

Ho creato un semplice pacchetto nuget che puoi includere nel tuo progetto che si occuperà di questo per te: https://www.nuget.org/packages/MSBuildGitHash/

Questo pacchetto nuget implementa una soluzione MSBuild "pura". Se preferisci non dipendere da un pacchetto nuget, puoi semplicemente copiare questi Target nel tuo file csproj e dovrebbe includere l'hash git come attributo di assembly personalizzato:

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

Ci sono due obiettivi qui. Il primo, "GetGitHash", carica l'hash git in una proprietà MSBuild denominata BuildHash, lo fa solo se BuildHash non è già definito. Ciò ti consente di passarlo a MSBuild dalla riga di comando, se preferisci. Puoi passarlo a MSBuild in questo modo:

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

La seconda destinazione, "WriteGitHash", scriverà il valore hash in un file nella cartella temporanea "obj" denominata "CustomAssemblyInfo.cs". Questo file conterrà una riga simile a:

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

Questo file CustomAssemblyInfo.cs verrà compilato nell'assembly, quindi puoi usare la reflection per cercare AssemblyMetadatain fase di esecuzione. Il codice seguente mostra come eseguire questa operazione quando la AssemblyInfoclasse è inclusa nello stesso assembly.

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

Alcuni vantaggi di questo design è che non tocca alcun file nella cartella del progetto, tutti i file modificati si trovano nella cartella "obj". Il progetto verrà anche compilato in modo identico da Visual Studio o dalla riga di comando. Può anche essere facilmente personalizzato per il tuo progetto e sarà controllato dal codice sorgente insieme al tuo file csproj.


2
Ha funzionato perfettamente. Ho installato il pacchetto nuget e sono stato in grado di estrarre l'hash git usando Assembly.GetExecutingAssembly(), quindi esaminando l'assembly CustomAttributes .
Gavin H

1
Se questa fosse la mia domanda, avrei accettato questa risposta. Roba fantastica.
Drew Noakes

1
@ GavinH, come hai ottenuto il GitHash? Posso vedere che il valore esiste ma esiste un metodo puro per ottenere l'attributo personalizzato in base al nome? Sembra che devo scrivere una lunga query dove selezionare CustomAttributes, grazie.
Okan Kocyigit

1
@ocanal sì, purtroppo non sono riuscito a trovare un modo più pulito per farlo che leggere il file CustomAttributes. Ad esempio, ecco la funzione che utilizzo per estrarre la stringa hash: pastebin.com/nVKGLhJC
Gavin H

2
@danmiser Non ho idea di cosa sia "UseMerge / SingleAssemblyName", quindi non posso aiutarti. Crea un problema su github.com/MarkPflug/MSBuildGitHash e potrei dare un'occhiata (non è una promessa).
MarkPflug

14

Un altro modo per farlo è usare NetRevisionTool con un po 'di magia integrata in Visual Studio. Lo mostrerò qui per Visual Studio 2013 Professional Edition, ma funzionerà anche con altre versioni.

Quindi prima scarica NetRevisionTool. Includere NetRevisionTool.exe nel PERCORSO o archiviarlo nel repository e creare una pre-compilazione di Visual Studio e un'azione di post-compilazione e modificare AssemblyInfo.cs.

Un esempio che aggiungerebbe il tuo git-hash a AssemblyInformationVersion sarebbe il seguente: Nelle impostazioni del tuo progetto:

inserisci qui la descrizione dell'immagine

nel AssemblyInfo.cs del tuo progetto cambi / aggiungi la riga:

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

nello screenshot mostrato ho controllato in NetRevisionTool.exe nella cartella External / bin

Dopo la compilazione, se fai clic con il pulsante destro del mouse sul file binario e vai alle proprietà, dovresti vedere qualcosa di simile al seguente:

inserisci qui la descrizione dell'immagine

Spero che questo aiuti qualcuno là fuori


L'hash di commit per me finisce sempre come 00000. Ho pensato che fosse perché avevo modifiche non salvate ma sempre lo stesso. Qualche idea sul perché?
Viktor

3
Il problema era che NetRevision non trovava il mio eseguibile git. Il motivo è perché stiamo usando SourceTree e git viene incorporato con esso. La soluzione era copiare git.exe e libiconv-2.dll da% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin nella cartella contenente NetRevision.exe. Ho anche dovuto modificare gli eventi in questo modo: Evento pre-compilazione: cd $ (ProjectDir) Librerie NetRevisionTool.exe / patch $ (ProjectDir) Evento post-compilazione: cd $ (ProjectDir) Librerie NetRevisionTool.exe / ripristino $ (ProjectDir)
Viktor

Solo per riferimento futuro, l'URL del repository del progetto è cambiato qualche tempo fa in github.com/ygoe/NetRevisionTool . Ulteriori informazioni sono disponibili anche su unclassified.software/apps/netrevisiontool .
ygoe

14

Penso che questa domanda valga la pena dare una risposta completa passo dopo passo. La strategia qui è eseguire uno script PowerShell dagli eventi di pre-compilazione che accetta un file modello e genera un file AssemblyInfo.cs con il tag git + le informazioni sul numero di commit incluse.

Passaggio 1: crea un file AssemblyInfo_template.cs nella cartella Project \ Properties, basato sul tuo AssemblyInfo.cs originale ma contenente:

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

Passaggio 2: creare uno script PowerShell denominato InjectGitVersion.ps1 la cui origine è:

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

Passaggio 3: salvare il file InjectGitVersion.ps1 nella directory della soluzione in una cartella BuildScripts

Passaggio 4: aggiungere la riga seguente agli eventi di pre-compilazione del progetto

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

Passaggio 5: crea il tuo progetto.

Passaggio 6: facoltativamente, aggiungi AssemblyInfo.cs al tuo file git ignore


E ricorda di rendere i tuoi tag git compatibili con le versioni dei file: come 1.2.3. Se hai tag più complicati, dovrai analizzare solo le parti compatibili
Atilio Jobson

2
Invece di usare un modello e gitignoring, AssemblyInfo.csuno reale potrebbe modificarlo AssemblyInfo.cssul posto, compilare , quindi ripristinare AssemblyInfo.csl'ultima versione con commit. Quindi nel repo ci sarebbe sempre stato AssemblyInfo.cs, con $..$sostituito solo per il tempo di compilazione.
Kuba Wyrostek

Funzionava benissimo. Ho finito per usare git describe --match "v[0-9]*" --long --always --dirtyper filtrare determinati tag (quelli contenenti un numero di versione) e per indicare se l'albero di lavoro era pulito.
packoman

Devi anche modificare la tua RegEx nello script PS:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
packoman

4

Ora è molto semplice con .NET Revision Task per MSBuild e lavorare con Visual Studio 2019.

È sufficiente installare il pacchetto NuGet Unclassified.NetRevisionTask , quindi configurare le informazioni desiderate nel AssemblyInfo.csfile come descritto nella documentazione di GitHub .

Se vuoi solo l'hash dell'ultimo commit (length = 8):

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

Costruisci il tuo progetto / soluzione e avrai qualcosa del genere:

inserisci qui la descrizione dell'immagine


Per configurare il formato in un'applicazione NET.core aggiungere il PropertyGroupal .csproj file, come visto nel README github.com/ygoe/NetRevisionTask/blob/master/README.md
sc911

3

Poiché l'altra risposta menziona già il bit git, una volta che hai SHA puoi considerare di generare il AssemblyInfo.csfile del tuo progetto in un hook pre-build.

Un modo per farlo è creare un AssemblyInfo.cs.tmplfile modello, con un segnaposto per il tuo SHA ad esempio $$ GITSHA $$, ad es.

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

L'hook di pre-compilazione deve quindi sostituire questo segnaposto e generare il file AssemblyInfo.cs per il compilatore C # da prelevare.

Per vedere come questo può essere fatto usando SubWCRev per SVN vedi questa risposta . Non dovrebbe essere difficile fare qualcosa di simile per git.

Altri modi potrebbero essere un "make stage" come accennato, ovvero scrivere un'attività MSBuild che fa qualcosa di simile. Ancora un altro modo potrebbe essere quello di post-processare la DLL in qualche modo (ildasm + ilasm dicono), ma penso che le opzioni sopra menzionate siano probabilmente le più semplici.


@Wint no, non aggiungere il AssemblyInfo.cs generato a git. Se lo fai sarà impossibile fare una build non sporca: P
scherzato il

3

Per un metodo di pagamento completamente automatizzato e flessibile https://github.com/Fody/Stamp . Lo abbiamo utilizzato con successo per i nostri progetti Git (così come questa versione per i progetti SVN)

Aggiornamento: questo è obsoleto poiché Stamp.Fody non è più mantenuto


1
sulla pagina github di Stamp.Fody dice: "Questo progetto non è più mantenuto.". Includendolo nel mio progetto ho sollevato un CA0052 e CA0055
sc911

2

È possibile utilizzare una riga di comando PowerShell per aggiornare tutti i file assemblyinfo con l'hash del commit.

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

1
  1. Spero che tu sappia come chiamare programmi esterni e intercettare l'output in fase di compilazione.
  2. Spero che tu sappia come fare in modo che la directory di lavoro di git ignori i file senza versione.

Come notato da @ learath2, l'output di git rev-parse HEADti darà un hash semplice.

Se usi i tag in Git-repository (e usi i tag, non è più descrittivo e leggibile di git rev-parse), l'output può essere ricevuto da git describe(anche se usato con successo in seguito git checkout)

Puoi chiamare rev-parse | descrivere in:

  • alcuni fanno tappa
  • nell'hook post-commit
  • nel filtro sfumino, se selezioni la modalità di implementazione dei filtri sfumino / pulisci

0

Sto usando una combinazione della risposta accettata e una piccola adizione. Ho installato l'estensione AutoT4 ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) per rieseguire i modelli prima della compilazione.

ottenere la versione da GIT

Ho git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"nel mio evento di pre-compilazione nelle proprietà del progetto. Aggiungere git_version.txt e VersionInfo.cs a .gitignore è una buona idea.

incorporare la versione nei metadati

Ho aggiunto un VersionInfo.ttmodello al mio progetto:

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

#>

Ora ho il mio tag git + hash in "ProductVersion".


0

Facendo riferimento a un'altra risposta ( https://stackoverflow.com/a/44278482/4537127 ) ho anche utilizzato il VersionInfo.ttmodello di testo per generare AssemblyInformationalVersionsenza AutoT4.

(Almeno funziona nella mia applicazione C # WPF)

Il problema era che gli eventi di pre-compilazione venivano eseguiti dopo le trasformazioni del modello, quindi dopo la clonazione il git_version.txtfile non era presente e la compilazione non riesce. Dopo averlo creato manualmente per consentire alla trasformazione di passare una volta, è stato aggiornato dopo la trasformazione ed era sempre un commit dietro .

Ho dovuto apportare due modifiche al file .csproj (questo vale almeno per Visual Studio Community 2017)

1) Importa gli obiettivi di trasformazione del testo e crea trasformazioni dei modelli da eseguire su ogni build: (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>

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

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

2) Effettua l' git describeesecuzione prima delle trasformazioni del modello (in modo che git_version.txtsia presente quando VersionInfo.ttviene trasformato):

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

..E il codice C # per ottenere il AssemblyInformationalVersion(Ref https://stackoverflow.com/a/7770189/4537127 )

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

        return attribute.InformationalVersion;
    }
}

..E aggiungi i file generati a .gitignore

VersionInfo.cs
git_version.txt

0

Un altro modo sarebbe generare un file Version.cs da un passaggio di pre-compilazione. L'ho esplorato in un piccolo progetto proof-of-concept che stampa il suo hash di commit corrente.

Il progetto è caricato su https://github.com/sashoalm/GitCommitHashPrinter .

Il codice batch che crea il file Version.cs è questo:

@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

Posto

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

nel 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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.