Skip to content
This repository was archived by the owner on Dec 2, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AssemblyToProcess/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
[assembly: AssemblyTitle("AssemblyToProcess")]
[assembly: AssemblyProduct("AssemblyToProcess")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("4.5.6.7")]
//[assembly: AssemblyInformationalVersionAttribute("1.0.0.0/aString")]
1 change: 1 addition & 0 deletions AssemblyToProcessExistingAttribute/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
[assembly: AssemblyTitle("AssemblyToProcessExistingAttribute")]
[assembly: AssemblyProduct("AssemblyToProcessExistingAttribute")]
[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("4.5.6.7")]
[assembly: AssemblyInformationalVersionAttribute("%version3%+%branch%.%githash% %haschanges% %utcnow% %now:yyMMdd%")]
55 changes: 43 additions & 12 deletions Fody/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

public class Configuration
{
public bool UseProject;
public string ChangeString = "HasChanges";
public bool UseProject { get; set; }
public bool UseFileVersion { get; set; }
public bool OverwriteFileVersion { get; set; } = true;

public string ChangeString { get; set; } = "HasChanges";

public Configuration(XElement config)
{
Expand All @@ -14,22 +17,50 @@ public Configuration(XElement config)
}

var attr = config.Attribute("UseProjectGit");
if (attr != null)
if (HasValue(attr))
{
try
{
UseProject = Convert.ToBoolean(attr.Value);
}
catch (Exception)
{
throw new WeavingException($"Unable to parse '{attr.Value}' as a boolean, please use true or false.");
}
UseProject = ConvertAndThrowIfNotBoolean(attr.Value);
}

attr = config.Attribute("UseFileVersion");
if (HasValue(attr))
{
UseFileVersion = ConvertAndThrowIfNotBoolean(attr.Value);
}

attr = config.Attribute("ChangeString");
if (!string.IsNullOrWhiteSpace(attr?.Value))
if (HasValue(attr))
{
ChangeString = attr.Value;
}

if (UseFileVersion)
OverwriteFileVersion = false;
else
{
attr = config.Attribute("OverwriteFileVersion");
if (HasValue(attr))
{
OverwriteFileVersion = ConvertAndThrowIfNotBoolean(attr.Value);
}
}
}

private static bool HasValue(XAttribute attr)
{
return !string.IsNullOrWhiteSpace(attr?.Value);
}

private static bool ConvertAndThrowIfNotBoolean(string value)
{
try
{
var result = Convert.ToBoolean(value);
return result;
}
catch
{
throw new WeavingException($"Unable to parse '{value}' as a boolean; please use 'true' or 'false'.");
}
}
}
18 changes: 9 additions & 9 deletions Fody/Internal/FormatStringTokenResolver.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System;
using System.Text.RegularExpressions;
using LibGit2Sharp;
using Mono.Cecil;

namespace Stamp.Fody.Internal
{
internal class FormatStringTokenResolver
using Version = System.Version;

internal static class FormatStringTokenResolver
{
private static Regex reEnvironmentToken = new Regex(@"%env\[([^\]]+)]%");
private static Regex reNow = new Regex(@"%now:([^%]+)%");
Expand All @@ -14,16 +15,15 @@ internal class FormatStringTokenResolver
private static DateTime now = DateTime.Now;
private static DateTime utcNow = DateTime.UtcNow;

public string ReplaceTokens(string template, ModuleDefinition moduleDefinition, Repository repo, string changestring)
public static string ReplaceTokens(string template, Version version, Repository repo, string changestring)
{
var assemblyVersion = moduleDefinition.Assembly.Name.Version;
var branch = repo.Head;

template = template.Replace("%version%", assemblyVersion.ToString());
template = template.Replace("%version1%", assemblyVersion.ToString(1));
template = template.Replace("%version2%", assemblyVersion.ToString(2));
template = template.Replace("%version3%", assemblyVersion.ToString(3));
template = template.Replace("%version4%", assemblyVersion.ToString(4));
template = template.Replace("%version%", version.ToString());
template = template.Replace("%version1%", version.ToString(1));
template = template.Replace("%version2%", version.ToString(2));
template = template.Replace("%version3%", version.ToString(3));
template = template.Replace("%version4%", version.ToString(4));

template = template.Replace("%now%", now.ToShortDateString());
template = template.Replace("%utcnow%", utcNow.ToShortDateString());
Expand Down
44 changes: 34 additions & 10 deletions Fody/ModuleWeaver.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;

Expand All @@ -15,16 +16,18 @@
public class ModuleWeaver : BaseModuleWeaver
{
private static bool isPathSet;
private readonly FormatStringTokenResolver formatStringTokenResolver;
private string assemblyInfoVersion;
private Version assemblyVersion;
private Version versionToUse;
private bool dotGitDirExists;


private const string InfoAttributeName = nameof(System.Reflection.AssemblyInformationalVersionAttribute);
private const string FileAttributeName = nameof(System.Reflection.AssemblyFileVersionAttribute);

public ModuleWeaver()
{
LogInfo = s => { };
LogWarning = s => { };
formatStringTokenResolver = new FormatStringTokenResolver();
}

public override void Execute()
Expand Down Expand Up @@ -57,13 +60,16 @@ public override void Execute()
return;
}

assemblyVersion = ModuleDefinition.Assembly.Name.Version;
if (!config.UseFileVersion)
versionToUse = ModuleDefinition.Assembly.Name.Version;
else
versionToUse = GetAssemblyFileVersion(customAttributes);

var customAttribute = customAttributes.FirstOrDefault(x => x.AttributeType.Name == "AssemblyInformationalVersionAttribute");
var customAttribute = GetCustomAttribute(customAttributes, InfoAttributeName);
if (customAttribute != null)
{
assemblyInfoVersion = (string)customAttribute.ConstructorArguments[0].Value;
assemblyInfoVersion = formatStringTokenResolver.ReplaceTokens(assemblyInfoVersion, ModuleDefinition, repo, config.ChangeString);
assemblyInfoVersion = FormatStringTokenResolver.ReplaceTokens(assemblyInfoVersion, versionToUse, repo, config.ChangeString);
VerifyStartsWithVersion(assemblyInfoVersion);
customAttribute.ConstructorArguments[0] = new CustomAttributeArgument(ModuleDefinition.TypeSystem.String, assemblyInfoVersion);
}
Expand All @@ -73,14 +79,32 @@ public override void Execute()
var constructor = ModuleDefinition.ImportReference(versionAttribute.Methods.First(x => x.IsConstructor));
customAttribute = new CustomAttribute(constructor);

assemblyInfoVersion = $"{assemblyVersion} Head:'{repo.Head.FriendlyName}' Sha:{branch.Tip.Sha}{(repo.IsClean() ? "" : " " + config.ChangeString)}";
assemblyInfoVersion = $"{versionToUse} Head:'{repo.Head.FriendlyName}' Sha:{branch.Tip.Sha}{(repo.IsClean() ? "" : " " + config.ChangeString)}";

customAttribute.ConstructorArguments.Add(new CustomAttributeArgument(ModuleDefinition.TypeSystem.String, assemblyInfoVersion));
customAttributes.Add(customAttribute);
}
}
}

private static CustomAttribute GetCustomAttribute(ICollection<CustomAttribute> attributes, string attributeName)
{
return attributes.FirstOrDefault(x => x.AttributeType.Name == attributeName);
}

private Version GetAssemblyFileVersion(ICollection<CustomAttribute> customAttributes)
{
var afvAttribute = GetCustomAttribute(customAttributes, FileAttributeName);
if (afvAttribute == null)
{
throw new WeavingException("AssemblyFileVersion attribute could not be found.");
}

var assemblyFileVersionString = (string) afvAttribute.ConstructorArguments[0].Value;
VerifyStartsWithVersion(assemblyFileVersionString);
return Version.Parse(assemblyFileVersionString);
}

private void VerifyStartsWithVersion(string versionString)
{
var prefix = new string(versionString.TakeWhile(x => char.IsDigit(x) || x == '.').ToArray());
Expand Down Expand Up @@ -166,15 +190,15 @@ public override void AfterWeaving()
var versions = reader.Read();

var fixedFileInfo = versions.FixedFileInfo.Value;
fixedFileInfo.FileVersion = assemblyVersion;
fixedFileInfo.ProductVersion = assemblyVersion;
fixedFileInfo.FileVersion = versionToUse;
fixedFileInfo.ProductVersion = versionToUse;
versions.FixedFileInfo = fixedFileInfo;

foreach (var stringTable in versions.StringFileInfo)
{
if (stringTable.Values.ContainsKey("FileVersion"))
{
stringTable.Values["FileVersion"] = assemblyVersion.ToString();
stringTable.Values["FileVersion"] = versionToUse.ToString();
}

if (stringTable.Values.ContainsKey("ProductVersion"))
Expand Down
5 changes: 5 additions & 0 deletions Fody/WeavingException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ public WeavingException(string message)
{

}

/// <inheritdoc />
public WeavingException(string message, Exception innerException) : base(message, innerException)
{
}
}
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Extracts the git information from disk, combines it with the assembly version, a
So if your assembly version is `1.0.0.0`, the working branch is `master` and the last commit is `759e9ddb53271dfa9335a3b27e452749a9b22280` then the following attribute will be added to the assembly.

```c#
[assembly: AssemblyInformationalVersion("1.0.0.0 Head:'master' Sha:759e9ddb53271dfa9335a3b27e452749a9b22280")]
[assembly: AssemblyInformationalVersion("1.0.0.0 Head:'master' Sha:759e9ddb53271dfa9335a3b27e452749a9b22280")]
```


Expand All @@ -52,6 +52,8 @@ The tokens are:
- `%version4%` is replaced with the major, minor, revision, and build version (`1.0.0.0`)
- `%now%` is replaced with the current short date
- `%utcnow%` is replaced with the current utc short date
- `%now%` is replaced with the current short date
- `%utcnow%` is replaced with the current utc short date
- `%githash%` is replaced with the SHA1 hash of the branch tip of the repository
- `%shorthash%` is replaced with the first eight characters of `%githash%`
- `%branch%` is replaced with the branch name of the repository
Expand All @@ -78,7 +80,6 @@ Define the string used to indicate that the code was built from a non clean repo
<Stamp ChangeString="New text" />
```


### UseProjectGit

Define if you want to start Stamp to start searching for the Git repository in the ProjectDir (`true`) or the SolutionDir (`false`).
Expand All @@ -89,6 +90,28 @@ Define if you want to start Stamp to start searching for the Git repository in t
<Stamp UseProjectGit='true' />
```

### OverwriteFileVersion

(new in 2.0)

By default, Stamp will overwrite the `AssemblyFileVersion` with the `AssemblyVersion`. Setting this to `false` will preserve the existing `AssemblyFileVersion`.

*Default is `true`*

```xml
<Stamp OverwriteFileVersion='false' />
```

### UseFileVersion

(new in 2.0)

By default, Stamp uses the value from `AssemblyVersion` to construct the `AssemblyInformationalVersion`. Set this to `true` to use the `AssemblyFileVersion` instead. **Note:** If this is set to `true`, `OverwriteFileVersion` will be `false` and will ignore any value explicitly set.

*Default is `false`*
```xml
<Stamp UseFileVersion='true' />
```

## Icon

Expand Down
16 changes: 16 additions & 0 deletions Tests/OverwriteFileVersionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Xml.Linq;
using NUnit.Framework;

namespace Stamp.Fody.Tests
{
[TestFixture]
class OverwriteFileVersionTests : PatchAssemblyTests
{

static XElement Config = XElement.Parse("<Stamp OverwriteFileVersion=\"false\" />");

public OverwriteFileVersionTests(): base(Config)
{
}
}
}
9 changes: 8 additions & 1 deletion Tests/PatchAssemblyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
{
using System;
using System.Diagnostics;
using System.Xml.Linq;
using NUnit.Framework;

public class PatchAssemblyTests : PatchAssemblyTestsBase
{
public PatchAssemblyTests() : base("AssemblyToProcess")
private const string AssemblyName = "AssemblyToProcess";

public PatchAssemblyTests() : base(AssemblyName)
{
}

protected PatchAssemblyTests(XElement config) : base(AssemblyName, config)
{
}

Expand Down
7 changes: 4 additions & 3 deletions Tests/PatchAssemblyTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Mono.Cecil;
using NUnit.Framework;

Expand All @@ -14,9 +15,8 @@ public abstract class PatchAssemblyTestsBase
private readonly string _patchedAssemblyPath;
private readonly Assembly _patchedAssembly;
private readonly string _assemblyToPatchPath;


protected PatchAssemblyTestsBase(string assemblyName)
protected PatchAssemblyTestsBase(string assemblyName, XElement config = null)
{
GetAssemblyToPatchPath(assemblyName);

Expand All @@ -36,7 +36,8 @@ protected PatchAssemblyTestsBase(string assemblyName)
ModuleDefinition = moduleDefinition,
AddinDirectoryPath = currentDirectory,
SolutionDirectoryPath = currentDirectory,
AssemblyFilePath = _patchedAssemblyPath
AssemblyFilePath = _patchedAssemblyPath,
Config = config
};

weavingTask.Execute();
Expand Down
2 changes: 2 additions & 0 deletions Tests/Stamp.Fody.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@
<ItemGroup>
<Compile Include="Helpers\AssemblyLocation.cs" />
<Compile Include="IntegrationTests\GitTests.cs" />
<Compile Include="OverwriteFileVersionTests.cs" />
<Compile Include="PatchAssemblyTestsBase.cs" />
<Compile Include="PatchExistingAssemblyTests.cs" />
<Compile Include="TokenResolverTests.cs" />
<Compile Include="Helpers\Verifier.cs" />
<Compile Include="PatchAssemblyTests.cs" />
<Compile Include="UseFileVersionTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
Expand Down
3 changes: 2 additions & 1 deletion Tests/Stamp.Fody.Tests.csproj.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helpers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helpers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=integrationtests/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Loading