Fixing versions
- Added --version-suffix to build and publish - Support reading DOTNET_* version variables everywhere versions can be read - Show the commit sha in dotnet --version - Added tests that check the assembly output version - Set DOTNET_BUILD_VERSION when producing the CLI app itself so that it has the version information stamped in for help.
This commit is contained in:
parent
02e39cf81d
commit
69b5e3f815
17 changed files with 297 additions and 35 deletions
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"dnx": {
|
||||
"projects": "src/*/project.json;test/src/*/project.json;scripts/*/project.json"
|
||||
"projects": "src/*/project.json;test/*/project.json;scripts/*/project.json"
|
||||
}
|
||||
}
|
|
@ -135,12 +135,18 @@ namespace Microsoft.DotNet.Cli.Build.Framework
|
|||
|
||||
public Command Environment(IDictionary<string, string> env)
|
||||
{
|
||||
foreach(var item in env)
|
||||
foreach (var item in env)
|
||||
{
|
||||
_process.StartInfo.Environment[item.Key] = item.Value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command Environment(string key, string value)
|
||||
{
|
||||
_process.StartInfo.Environment[key] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandResult Execute()
|
||||
{
|
||||
|
|
|
@ -157,11 +157,14 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
|
||||
var configuration = c.BuildContext.Get<string>("Configuration");
|
||||
var binDir = Path.Combine(outputDir, "bin");
|
||||
var buildVesion = c.BuildContext.Get<BuildVersion>("BuildVersion");
|
||||
|
||||
Mkdirp(binDir);
|
||||
|
||||
foreach (var project in ProjectsToPublish)
|
||||
{
|
||||
// TODO: Use the flag once we get a full build round tripped
|
||||
// --version-suffix buildVesion.VersionSuffix
|
||||
dotnet.Publish(
|
||||
"--native-subdirectory",
|
||||
"--output",
|
||||
|
@ -169,6 +172,7 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
"--configuration",
|
||||
configuration,
|
||||
Path.Combine(c.BuildContext.BuildDirectory, "src", project))
|
||||
.Environment("DOTNET_BUILD_VERSION", buildVesion.VersionSuffix)
|
||||
.Execute()
|
||||
.EnsureSuccessful();
|
||||
}
|
||||
|
@ -210,7 +214,7 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
}
|
||||
|
||||
// Generate .version file
|
||||
var version = c.BuildContext.Get<BuildVersion>("BuildVersion").SimpleVersion;
|
||||
var version = buildVesion.SimpleVersion;
|
||||
var content = $@"{c.BuildContext["CommitHash"]}{Environment.NewLine}{version}{Environment.NewLine}";
|
||||
File.WriteAllText(Path.Combine(outputDir, ".version"), content);
|
||||
|
||||
|
|
|
@ -84,6 +84,17 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
.Build();
|
||||
}
|
||||
|
||||
public static ProjectContextBuilder CreateBuilder(string projectPath, NuGetFramework framework)
|
||||
{
|
||||
if (projectPath.EndsWith(Project.FileName))
|
||||
{
|
||||
projectPath = Path.GetDirectoryName(projectPath);
|
||||
}
|
||||
return new ProjectContextBuilder()
|
||||
.WithProjectDirectory(projectPath)
|
||||
.WithTargetFramework(framework);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a project context for each framework located in the project at <paramref name="projectPath"/>
|
||||
/// </summary>
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
|
||||
private Func<string, LockFile> LockFileResolver { get; set; }
|
||||
|
||||
private ProjectReaderSettings Settings { get; set; }
|
||||
private ProjectReaderSettings Settings { get; set; } = ProjectReaderSettings.ReadFromEnvironment();
|
||||
|
||||
public ProjectContextBuilder()
|
||||
{
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
namespace Microsoft.DotNet.ProjectModel
|
||||
using System;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel
|
||||
{
|
||||
public class ProjectReaderSettings
|
||||
{
|
||||
public string VersionSuffix { get; set; }
|
||||
public string AssemblyFileVersion { get; set; }
|
||||
|
||||
public static ProjectReaderSettings ReadFromEnvironment()
|
||||
{
|
||||
var settings = new ProjectReaderSettings
|
||||
{
|
||||
VersionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION"),
|
||||
AssemblyFileVersion = Environment.GetEnvironmentVariable("DOTNET_ASSEMBLY_FILE_VERSION")
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.Tools.Test;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using NuGet.Frameworks;
|
||||
using Microsoft.DotNet.ProjectModel.Server;
|
||||
using Microsoft.DotNet.Tools.Build;
|
||||
using Microsoft.DotNet.Tools.Compiler;
|
||||
|
@ -14,13 +18,10 @@ using Microsoft.DotNet.Tools.Compiler.Native;
|
|||
using Microsoft.DotNet.Tools.Help;
|
||||
using Microsoft.DotNet.Tools.New;
|
||||
using Microsoft.DotNet.Tools.Publish;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Microsoft.DotNet.Tools.Restore;
|
||||
using NuGet.Frameworks;
|
||||
using Microsoft.DotNet.Tools.Resgen;
|
||||
using Microsoft.DotNet.Tools.Run;
|
||||
using Microsoft.DotNet.Tools.Test;
|
||||
using Microsoft.DotNet.Tools.Repl;
|
||||
using Microsoft.DotNet.Tools.Resgen;
|
||||
using Microsoft.DotNet.Tools.Restore;
|
||||
using Microsoft.DotNet.Tools.Run;
|
||||
|
||||
namespace Microsoft.DotNet.Cli
|
||||
{
|
||||
|
@ -134,6 +135,12 @@ namespace Microsoft.DotNet.Cli
|
|||
{
|
||||
HelpCommand.PrintVersionHeader();
|
||||
|
||||
var commitSha = GetCommitSha();
|
||||
Reporter.Output.WriteLine();
|
||||
Reporter.Output.WriteLine("Product Information:");
|
||||
Reporter.Output.WriteLine($" Version: {HelpCommand.ProductVersion}");
|
||||
Reporter.Output.WriteLine($" Commit Sha: {commitSha.Substring(0, 10)}");
|
||||
Reporter.Output.WriteLine();
|
||||
var runtimeEnvironment = PlatformServices.Default.Runtime;
|
||||
Reporter.Output.WriteLine("Runtime Environment:");
|
||||
Reporter.Output.WriteLine($" OS Name: {runtimeEnvironment.OperatingSystem}");
|
||||
|
@ -151,5 +158,18 @@ namespace Microsoft.DotNet.Cli
|
|||
{
|
||||
return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName));
|
||||
}
|
||||
|
||||
private static string GetCommitSha()
|
||||
{
|
||||
// The CLI ships with a .version file that stores the commit information
|
||||
var versionFile = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", ".version"));
|
||||
|
||||
if (File.Exists(versionFile))
|
||||
{
|
||||
return File.ReadLines(versionFile).FirstOrDefault();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,8 +284,8 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
var args = new List<string>();
|
||||
|
||||
args.Add("--framework");
|
||||
args.Add($"{projectDependency.Framework}");
|
||||
|
||||
args.Add($"{projectDependency.Framework}");
|
||||
|
||||
args.Add("--configuration");
|
||||
args.Add(_args.ConfigValue);
|
||||
args.Add(projectDependency.Project.ProjectDirectory);
|
||||
|
@ -296,6 +296,12 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
args.Add(_args.RuntimeValue);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_args.VersionSuffixValue))
|
||||
{
|
||||
args.Add("--version-suffix");
|
||||
args.Add(_args.VersionSuffixValue);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_args.BuildBasePathValue))
|
||||
{
|
||||
args.Add("--build-base-path");
|
||||
|
@ -312,7 +318,7 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
// todo: add methods to CompilerCommandApp to generate the arg string?
|
||||
var args = new List<string>();
|
||||
args.Add("--framework");
|
||||
args.Add(_rootProject.TargetFramework.ToString());
|
||||
args.Add(_rootProject.TargetFramework.ToString());
|
||||
args.Add("--configuration");
|
||||
args.Add(_args.ConfigValue);
|
||||
|
||||
|
@ -328,6 +334,12 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
args.Add(_args.OutputValue);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_args.VersionSuffixValue))
|
||||
{
|
||||
args.Add("--version-suffix");
|
||||
args.Add(_args.VersionSuffixValue);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_args.BuildBasePathValue))
|
||||
{
|
||||
args.Add("--build-base-path");
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
private CommandOption _buildBasePath;
|
||||
private CommandOption _frameworkOption;
|
||||
private CommandOption _runtimeOption;
|
||||
private CommandOption _versionSuffixOption;
|
||||
private CommandOption _configurationOption;
|
||||
private CommandArgument _projectArgument;
|
||||
private CommandOption _nativeOption;
|
||||
|
@ -41,7 +42,8 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
public string ProjectPathValue { get; set; }
|
||||
public string BuildBasePathValue { get; set; }
|
||||
public string OutputValue { get; set; }
|
||||
public string RuntimeValue{ get; set; }
|
||||
public string RuntimeValue { get; set; }
|
||||
public string VersionSuffixValue { get; set; }
|
||||
public string ConfigValue { get; set; }
|
||||
public bool IsNativeValue { get; set; }
|
||||
public string ArchValue { get; set; }
|
||||
|
@ -53,7 +55,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
public string CppCompilerFlagsValue { get; set; }
|
||||
|
||||
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params
|
||||
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
||||
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
||||
|
||||
public CompilerCommandApp(string name, string fullName, string description)
|
||||
{
|
||||
|
@ -78,6 +80,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
_frameworkOption = _app.Option("-f|--framework <FRAMEWORK>", "Compile a specific framework", CommandOptionType.MultipleValue);
|
||||
_configurationOption = _app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
|
||||
_runtimeOption = _app.Option("-r|--runtime <RUNTIME_IDENTIFIER>", "Target runtime to publish for", CommandOptionType.SingleValue);
|
||||
_versionSuffixOption = _app.Option("--version-suffix <VERSION_SUFFIX>", "Defines what `*` should be replaced with in version field in project.json", CommandOptionType.SingleValue);
|
||||
_projectArgument = _app.Argument("<PROJECT>", "The project to compile, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||
|
||||
// Native Args
|
||||
|
@ -106,6 +109,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
BuildBasePathValue = _buildBasePath.Value();
|
||||
ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration;
|
||||
RuntimeValue = _runtimeOption.Value();
|
||||
VersionSuffixValue = _versionSuffixOption.Value();
|
||||
|
||||
IsNativeValue = _nativeOption.HasValue();
|
||||
ArchValue = _archOption.Value();
|
||||
|
@ -117,11 +121,24 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
CppCompilerFlagsValue = _cppCompilerFlagsOption.Value();
|
||||
|
||||
IEnumerable<ProjectContext> contexts;
|
||||
|
||||
// Set defaults based on the environment
|
||||
var settings = ProjectReaderSettings.ReadFromEnvironment();
|
||||
|
||||
if (!string.IsNullOrEmpty(VersionSuffixValue))
|
||||
{
|
||||
settings.VersionSuffix = VersionSuffixValue;
|
||||
}
|
||||
|
||||
if (_frameworkOption.HasValue())
|
||||
{
|
||||
contexts = _frameworkOption.Values
|
||||
.Select(f => ProjectContext.Create(ProjectPathValue, NuGetFramework.Parse(f)));
|
||||
.Select(f =>
|
||||
{
|
||||
return ProjectContext.CreateBuilder(ProjectPathValue, NuGetFramework.Parse(f))
|
||||
.WithReaderSettings(settings)
|
||||
.Build();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -131,7 +148,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
else
|
||||
{
|
||||
contexts = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings: null);
|
||||
contexts = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,11 +162,12 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
|
||||
public CompilerCommandApp ShallowCopy()
|
||||
{
|
||||
return (CompilerCommandApp) MemberwiseClone();
|
||||
return (CompilerCommandApp)MemberwiseClone();
|
||||
}
|
||||
|
||||
// CommandOptionType is internal. Cannot pass it as argument. Therefore the method name encodes the option type.
|
||||
protected void AddNoValueOption(string optionTemplate, string descriptino){
|
||||
protected void AddNoValueOption(string optionTemplate, string descriptino)
|
||||
{
|
||||
baseClassOptions[optionTemplate] = _app.Option(optionTemplate, descriptino, CommandOptionType.NoValue);
|
||||
}
|
||||
|
||||
|
@ -169,7 +187,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
else
|
||||
{
|
||||
return new [] { RuntimeValue };
|
||||
return new[] { RuntimeValue };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ Common Commands:
|
|||
run Compiles and immediately executes a .NET project
|
||||
repl Launch an interactive session (read, eval, print, loop)
|
||||
pack Creates a NuGet package";
|
||||
private static readonly string ProductVersion = GetProductVersion();
|
||||
public static readonly string ProductVersion = GetProductVersion();
|
||||
|
||||
private static string GetProductVersion()
|
||||
{
|
||||
|
|
|
@ -51,9 +51,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
|
||||
// Set defaults based on the environment
|
||||
var settings = new ProjectReaderSettings();
|
||||
settings.VersionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION");
|
||||
settings.AssemblyFileVersion = Environment.GetEnvironmentVariable("DOTNET_ASSEMBLY_FILE_VERSION");
|
||||
var settings = ProjectReaderSettings.ReadFromEnvironment();
|
||||
|
||||
if (versionSuffix.HasValue())
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
var runtime = app.Option("-r|--runtime <RUNTIME_IDENTIFIER>", "Target runtime to publish for", CommandOptionType.SingleValue);
|
||||
var buildBasePath = app.Option("-b|--build-base-path <OUTPUT_DIR>", "Directory in which to place temporary outputs", CommandOptionType.SingleValue);
|
||||
var output = app.Option("-o|--output <OUTPUT_PATH>", "Path in which to publish the app", CommandOptionType.SingleValue);
|
||||
var versionSuffix = app.Option("--version-suffix <VERSION_SUFFIX>", "Defines what `*` should be replaced with in version field in project.json", CommandOptionType.SingleValue);
|
||||
var configuration = app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
|
||||
var projectPath = app.Argument("<PROJECT>", "The project to publish, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||
var nativeSubdirectories = app.Option("--native-subdirectory", "Temporary mechanism to include subdirectories from native assets of dependency packages in output", CommandOptionType.NoValue);
|
||||
|
@ -39,6 +40,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
publish.Configuration = configuration.Value() ?? Constants.DefaultConfiguration;
|
||||
publish.NativeSubdirectories = nativeSubdirectories.HasValue();
|
||||
publish.ProjectPath = projectPath.Value;
|
||||
publish.VersionSuffix = versionSuffix.Value();
|
||||
|
||||
if (string.IsNullOrEmpty(publish.ProjectPath))
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
public bool NativeSubdirectories { get; set; }
|
||||
public NuGetFramework NugetFramework { get; set; }
|
||||
public IEnumerable<ProjectContext> ProjectContexts { get; set; }
|
||||
|
||||
public string VersionSuffix { get; set; }
|
||||
public int NumberOfProjects { get; private set; }
|
||||
public int NumberOfPublishedProjects { get; private set; }
|
||||
|
||||
|
@ -80,12 +80,12 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
/// <param name="configuration">Debug or Release</param>
|
||||
/// <param name="nativeSubdirectories"></param>
|
||||
/// <returns>Return 0 if successful else return non-zero</returns>
|
||||
private static bool PublishProjectContext(ProjectContext context, string buildBasePath, string outputPath, string configuration, bool nativeSubdirectories)
|
||||
private bool PublishProjectContext(ProjectContext context, string buildBasePath, string outputPath, string configuration, bool nativeSubdirectories)
|
||||
{
|
||||
Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}");
|
||||
|
||||
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
outputPath = context.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeOutputPath;
|
||||
|
@ -118,6 +118,13 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
configuration,
|
||||
context.ProjectFile.ProjectDirectory
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(VersionSuffix))
|
||||
{
|
||||
args.Add("--version-suffix");
|
||||
args.Add(VersionSuffix);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(buildBasePath))
|
||||
{
|
||||
args.Add("--build-base-path");
|
||||
|
@ -228,7 +235,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
{
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
}
|
||||
|
||||
|
||||
File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, Path.GetFileName(file.ResolvedPath)), overwrite: true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
private string _buidBasePathDirectory;
|
||||
private string _configuration;
|
||||
private string _framework;
|
||||
private string _versionSuffix;
|
||||
private bool _noHost;
|
||||
private bool _native;
|
||||
private string _architecture;
|
||||
|
@ -66,6 +67,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
$"--framework {_framework}";
|
||||
}
|
||||
}
|
||||
|
||||
private string VersionSuffixOption
|
||||
{
|
||||
get
|
||||
{
|
||||
return _versionSuffix == string.Empty ?
|
||||
"" :
|
||||
$"--version-suffix {_versionSuffix}";
|
||||
}
|
||||
}
|
||||
|
||||
private string NoHostOption
|
||||
{
|
||||
|
@ -183,6 +194,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
string buidBasePath="",
|
||||
string configuration="",
|
||||
string framework="",
|
||||
string versionSuffix="",
|
||||
bool noHost=false,
|
||||
bool native=false,
|
||||
string architecture="",
|
||||
|
@ -203,6 +215,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
_outputDirectory = output;
|
||||
_buidBasePathDirectory = buidBasePath;
|
||||
_configuration = configuration;
|
||||
_versionSuffix = versionSuffix;
|
||||
_framework = framework;
|
||||
_noHost = noHost;
|
||||
_native = native;
|
||||
|
@ -238,7 +251,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
|
||||
private string BuildArgs()
|
||||
{
|
||||
return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
||||
return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {VersionSuffixOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,16 @@ using Microsoft.DotNet.Cli.Utils;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||
{
|
||||
public class TestCommand
|
||||
{
|
||||
protected string _command;
|
||||
|
||||
|
||||
public Dictionary<string, string> Environment { get; } = new Dictionary<string, string>();
|
||||
|
||||
public TestCommand(string command)
|
||||
{
|
||||
_command = command;
|
||||
|
@ -63,9 +66,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
RedirectStandardOutput = true
|
||||
};
|
||||
|
||||
foreach (var item in Environment)
|
||||
{
|
||||
psi.Environment[item.Key] = item.Value;
|
||||
}
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = psi
|
||||
StartInfo = psi,
|
||||
};
|
||||
|
||||
process.EnableRaisingEvents = true;
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using FluentAssertions.Common;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using NuGet.Frameworks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||
|
@ -93,6 +90,44 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
|||
appruntime.Should().Exist().And.HaveFiles(_runtimeFiles);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SettingVersionInEnvironment_ShouldStampedAssemblyInfoInOutputAssembly()
|
||||
{
|
||||
var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithConfiguration")
|
||||
.WithLockFiles();
|
||||
|
||||
var cmd = new BuildCommand(Path.Combine(testInstance.TestRoot, Project.FileName), framework: DefaultFramework);
|
||||
cmd.Environment["DOTNET_BUILD_VERSION"] = "85";
|
||||
cmd.Environment["DOTNET_ASSEMBLY_FILE_VERSION"] = "345";
|
||||
cmd.ExecuteWithCapturedOutput().Should().Pass();
|
||||
|
||||
var output = Path.Combine(testInstance.TestRoot, "bin", "Debug", DefaultFramework, "TestLibraryWithConfiguration.dll");
|
||||
var informationalVersion = PeReaderUtils.GetAssemblyAttributeValue(output, "AssemblyInformationalVersionAttribute");
|
||||
var fileVersion = PeReaderUtils.GetAssemblyAttributeValue(output, "AssemblyFileVersionAttribute");
|
||||
|
||||
informationalVersion.Should().NotBeNull();
|
||||
informationalVersion.Should().BeEquivalentTo("1.0.0-85");
|
||||
|
||||
fileVersion.Should().NotBeNull();
|
||||
fileVersion.Should().BeEquivalentTo("1.0.0.345");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SettingVersionSuffixFlag_ShouldStampedAssemblyInfoInOutputAssembly()
|
||||
{
|
||||
var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithConfiguration")
|
||||
.WithLockFiles();
|
||||
|
||||
var cmd = new BuildCommand(Path.Combine(testInstance.TestRoot, Project.FileName), framework: DefaultFramework, versionSuffix: "85");
|
||||
cmd.ExecuteWithCapturedOutput().Should().Pass();
|
||||
|
||||
var output = Path.Combine(testInstance.TestRoot, "bin", "Debug", DefaultFramework, "TestLibraryWithConfiguration.dll");
|
||||
var informationalVersion = PeReaderUtils.GetAssemblyAttributeValue(output, "AssemblyInformationalVersionAttribute");
|
||||
|
||||
informationalVersion.Should().NotBeNull();
|
||||
informationalVersion.Should().BeEquivalentTo("1.0.0-85");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResourceTest()
|
||||
{
|
||||
|
|
115
test/dotnet-build.Tests/PeReaderUtils.cs
Normal file
115
test/dotnet-build.Tests/PeReaderUtils.cs
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.PortableExecutable;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||
{
|
||||
public static class PeReaderUtils
|
||||
{
|
||||
internal static string GetAssemblyAttributeValue(string assemblyPath, string attributeName)
|
||||
{
|
||||
if (!File.Exists(assemblyPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var stream = File.OpenRead(assemblyPath))
|
||||
using (var peReader = new PEReader(stream))
|
||||
{
|
||||
if (!peReader.HasMetadata)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var mdReader = peReader.GetMetadataReader();
|
||||
var attrs = mdReader.GetAssemblyDefinition().GetCustomAttributes()
|
||||
.Select(ah => mdReader.GetCustomAttribute(ah));
|
||||
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
var ctorHandle = attr.Constructor;
|
||||
if (ctorHandle.Kind != HandleKind.MemberReference)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var container = mdReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent;
|
||||
var name = mdReader.GetTypeReference((TypeReferenceHandle)container).Name;
|
||||
if (!string.Equals(mdReader.GetString(name), attributeName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var arguments = GetFixedStringArguments(mdReader, attr);
|
||||
if (arguments.Count == 1)
|
||||
{
|
||||
return arguments[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fixed (required) string arguments of a custom attribute.
|
||||
/// Only attributes that have only fixed string arguments.
|
||||
/// </summary>
|
||||
private static List<string> GetFixedStringArguments(MetadataReader reader, CustomAttribute attribute)
|
||||
{
|
||||
// TODO: Nick Guerrera (Nick.Guerrera@microsoft.com) hacked this method for temporary use.
|
||||
// There is a blob decoder feature in progress but it won't ship in time for our milestone.
|
||||
// Replace this method with the blob decoder feature when later it is availale.
|
||||
|
||||
var signature = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor).Signature;
|
||||
var signatureReader = reader.GetBlobReader(signature);
|
||||
var valueReader = reader.GetBlobReader(attribute.Value);
|
||||
var arguments = new List<string>();
|
||||
|
||||
var prolog = valueReader.ReadUInt16();
|
||||
if (prolog != 1)
|
||||
{
|
||||
// Invalid custom attribute prolog
|
||||
return arguments;
|
||||
}
|
||||
|
||||
var header = signatureReader.ReadSignatureHeader();
|
||||
if (header.Kind != SignatureKind.Method || header.IsGeneric)
|
||||
{
|
||||
// Invalid custom attribute constructor signature
|
||||
return arguments;
|
||||
}
|
||||
|
||||
int parameterCount;
|
||||
if (!signatureReader.TryReadCompressedInteger(out parameterCount))
|
||||
{
|
||||
// Invalid custom attribute constructor signature
|
||||
return arguments;
|
||||
}
|
||||
|
||||
var returnType = signatureReader.ReadSignatureTypeCode();
|
||||
if (returnType != SignatureTypeCode.Void)
|
||||
{
|
||||
// Invalid custom attribute constructor signature
|
||||
return arguments;
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameterCount; i++)
|
||||
{
|
||||
var signatureTypeCode = signatureReader.ReadSignatureTypeCode();
|
||||
if (signatureTypeCode == SignatureTypeCode.String)
|
||||
{
|
||||
// Custom attribute constructor must take only strings
|
||||
arguments.Add(valueReader.ReadSerializedString());
|
||||
}
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue