Merge pull request #1471 from dotnet/davidfowl/fix-versions

Fixing versions
This commit is contained in:
David Fowler 2016-02-18 02:42:31 -08:00
commit 8645031db8
19 changed files with 341 additions and 48 deletions

View file

@ -1,5 +1,5 @@
{ {
"dnx": { "dnx": {
"projects": "src/*/project.json;test/src/*/project.json;scripts/*/project.json" "projects": "src/*/project.json;test/*/project.json;scripts/*/project.json"
} }
} }

View file

@ -135,12 +135,18 @@ namespace Microsoft.DotNet.Cli.Build.Framework
public Command Environment(IDictionary<string, string> env) public Command Environment(IDictionary<string, string> env)
{ {
foreach(var item in env) foreach (var item in env)
{ {
_process.StartInfo.Environment[item.Key] = item.Value; _process.StartInfo.Environment[item.Key] = item.Value;
} }
return this; return this;
} }
public Command Environment(string key, string value)
{
_process.StartInfo.Environment[key] = value;
return this;
}
public CommandResult Execute() public CommandResult Execute()
{ {

View file

@ -157,11 +157,14 @@ namespace Microsoft.DotNet.Cli.Build
var configuration = c.BuildContext.Get<string>("Configuration"); var configuration = c.BuildContext.Get<string>("Configuration");
var binDir = Path.Combine(outputDir, "bin"); var binDir = Path.Combine(outputDir, "bin");
var buildVesion = c.BuildContext.Get<BuildVersion>("BuildVersion");
Mkdirp(binDir); Mkdirp(binDir);
foreach (var project in ProjectsToPublish) foreach (var project in ProjectsToPublish)
{ {
// TODO: Use the flag once we get a full build round tripped
// --version-suffix buildVesion.VersionSuffix
dotnet.Publish( dotnet.Publish(
"--native-subdirectory", "--native-subdirectory",
"--output", "--output",
@ -169,6 +172,7 @@ namespace Microsoft.DotNet.Cli.Build
"--configuration", "--configuration",
configuration, configuration,
Path.Combine(c.BuildContext.BuildDirectory, "src", project)) Path.Combine(c.BuildContext.BuildDirectory, "src", project))
.Environment("DOTNET_BUILD_VERSION", buildVesion.VersionSuffix)
.Execute() .Execute()
.EnsureSuccessful(); .EnsureSuccessful();
} }
@ -210,7 +214,7 @@ namespace Microsoft.DotNet.Cli.Build
} }
// Generate .version file // 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}"; var content = $@"{c.BuildContext["CommitHash"]}{Environment.NewLine}{version}{Environment.NewLine}";
File.WriteAllText(Path.Combine(outputDir, ".version"), content); File.WriteAllText(Path.Combine(outputDir, ".version"), content);

View file

@ -84,6 +84,17 @@ namespace Microsoft.DotNet.ProjectModel
.Build(); .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> /// <summary>
/// Creates a project context for each framework located in the project at <paramref name="projectPath"/> /// Creates a project context for each framework located in the project at <paramref name="projectPath"/>
/// </summary> /// </summary>

View file

@ -36,7 +36,7 @@ namespace Microsoft.DotNet.ProjectModel
private Func<string, LockFile> LockFileResolver { get; set; } private Func<string, LockFile> LockFileResolver { get; set; }
private ProjectReaderSettings Settings { get; set; } private ProjectReaderSettings Settings { get; set; } = ProjectReaderSettings.ReadFromEnvironment();
public ProjectContextBuilder() public ProjectContextBuilder()
{ {

View file

@ -1,8 +1,21 @@
namespace Microsoft.DotNet.ProjectModel using System;
namespace Microsoft.DotNet.ProjectModel
{ {
public class ProjectReaderSettings public class ProjectReaderSettings
{ {
public string VersionSuffix { get; set; } public string VersionSuffix { get; set; }
public string AssemblyFileVersion { 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;
}
} }
} }

View file

@ -3,8 +3,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Microsoft.DotNet.Cli.Utils; 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.ProjectModel.Server;
using Microsoft.DotNet.Tools.Build; using Microsoft.DotNet.Tools.Build;
using Microsoft.DotNet.Tools.Compiler; using Microsoft.DotNet.Tools.Compiler;
@ -14,13 +18,10 @@ using Microsoft.DotNet.Tools.Compiler.Native;
using Microsoft.DotNet.Tools.Help; using Microsoft.DotNet.Tools.Help;
using Microsoft.DotNet.Tools.New; using Microsoft.DotNet.Tools.New;
using Microsoft.DotNet.Tools.Publish; 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.Repl;
using Microsoft.DotNet.Tools.Resgen;
using Microsoft.DotNet.Tools.Restore;
using Microsoft.DotNet.Tools.Run;
namespace Microsoft.DotNet.Cli namespace Microsoft.DotNet.Cli
{ {
@ -134,6 +135,12 @@ namespace Microsoft.DotNet.Cli
{ {
HelpCommand.PrintVersionHeader(); 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; var runtimeEnvironment = PlatformServices.Default.Runtime;
Reporter.Output.WriteLine("Runtime Environment:"); Reporter.Output.WriteLine("Runtime Environment:");
Reporter.Output.WriteLine($" OS Name: {runtimeEnvironment.OperatingSystem}"); 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)); 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;
}
} }
} }

View file

@ -284,8 +284,8 @@ namespace Microsoft.DotNet.Tools.Build
var args = new List<string>(); var args = new List<string>();
args.Add("--framework"); args.Add("--framework");
args.Add($"{projectDependency.Framework}"); args.Add($"{projectDependency.Framework}");
args.Add("--configuration"); args.Add("--configuration");
args.Add(_args.ConfigValue); args.Add(_args.ConfigValue);
args.Add(projectDependency.Project.ProjectDirectory); args.Add(projectDependency.Project.ProjectDirectory);
@ -296,6 +296,12 @@ namespace Microsoft.DotNet.Tools.Build
args.Add(_args.RuntimeValue); args.Add(_args.RuntimeValue);
} }
if (!string.IsNullOrEmpty(_args.VersionSuffixValue))
{
args.Add("--version-suffix");
args.Add(_args.VersionSuffixValue);
}
if (!string.IsNullOrWhiteSpace(_args.BuildBasePathValue)) if (!string.IsNullOrWhiteSpace(_args.BuildBasePathValue))
{ {
args.Add("--build-base-path"); args.Add("--build-base-path");
@ -312,7 +318,7 @@ namespace Microsoft.DotNet.Tools.Build
// todo: add methods to CompilerCommandApp to generate the arg string? // todo: add methods to CompilerCommandApp to generate the arg string?
var args = new List<string>(); var args = new List<string>();
args.Add("--framework"); args.Add("--framework");
args.Add(_rootProject.TargetFramework.ToString()); args.Add(_rootProject.TargetFramework.ToString());
args.Add("--configuration"); args.Add("--configuration");
args.Add(_args.ConfigValue); args.Add(_args.ConfigValue);
@ -328,6 +334,12 @@ namespace Microsoft.DotNet.Tools.Build
args.Add(_args.OutputValue); args.Add(_args.OutputValue);
} }
if (!string.IsNullOrEmpty(_args.VersionSuffixValue))
{
args.Add("--version-suffix");
args.Add(_args.VersionSuffixValue);
}
if (!string.IsNullOrEmpty(_args.BuildBasePathValue)) if (!string.IsNullOrEmpty(_args.BuildBasePathValue))
{ {
args.Add("--build-base-path"); args.Add("--build-base-path");

View file

@ -26,6 +26,7 @@ namespace Microsoft.DotNet.Tools.Compiler
private CommandOption _buildBasePath; private CommandOption _buildBasePath;
private CommandOption _frameworkOption; private CommandOption _frameworkOption;
private CommandOption _runtimeOption; private CommandOption _runtimeOption;
private CommandOption _versionSuffixOption;
private CommandOption _configurationOption; private CommandOption _configurationOption;
private CommandArgument _projectArgument; private CommandArgument _projectArgument;
private CommandOption _nativeOption; private CommandOption _nativeOption;
@ -41,7 +42,8 @@ namespace Microsoft.DotNet.Tools.Compiler
public string ProjectPathValue { get; set; } public string ProjectPathValue { get; set; }
public string BuildBasePathValue { get; set; } public string BuildBasePathValue { get; set; }
public string OutputValue { 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 string ConfigValue { get; set; }
public bool IsNativeValue { get; set; } public bool IsNativeValue { get; set; }
public string ArchValue { get; set; } public string ArchValue { get; set; }
@ -53,7 +55,7 @@ namespace Microsoft.DotNet.Tools.Compiler
public string CppCompilerFlagsValue { get; set; } public string CppCompilerFlagsValue { get; set; }
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params // 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) 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); _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); _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); _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"); _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 // Native Args
@ -106,6 +109,7 @@ namespace Microsoft.DotNet.Tools.Compiler
BuildBasePathValue = _buildBasePath.Value(); BuildBasePathValue = _buildBasePath.Value();
ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration; ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration;
RuntimeValue = _runtimeOption.Value(); RuntimeValue = _runtimeOption.Value();
VersionSuffixValue = _versionSuffixOption.Value();
IsNativeValue = _nativeOption.HasValue(); IsNativeValue = _nativeOption.HasValue();
ArchValue = _archOption.Value(); ArchValue = _archOption.Value();
@ -117,11 +121,24 @@ namespace Microsoft.DotNet.Tools.Compiler
CppCompilerFlagsValue = _cppCompilerFlagsOption.Value(); CppCompilerFlagsValue = _cppCompilerFlagsOption.Value();
IEnumerable<ProjectContext> contexts; IEnumerable<ProjectContext> contexts;
// Set defaults based on the environment
var settings = ProjectReaderSettings.ReadFromEnvironment();
if (!string.IsNullOrEmpty(VersionSuffixValue))
{
settings.VersionSuffix = VersionSuffixValue;
}
if (_frameworkOption.HasValue()) if (_frameworkOption.HasValue())
{ {
contexts = _frameworkOption.Values contexts = _frameworkOption.Values
.Select(f => ProjectContext.Create(ProjectPathValue, NuGetFramework.Parse(f))); .Select(f =>
{
return ProjectContext.CreateBuilder(ProjectPathValue, NuGetFramework.Parse(f))
.WithReaderSettings(settings)
.Build();
});
} }
else else
{ {
@ -131,7 +148,7 @@ namespace Microsoft.DotNet.Tools.Compiler
} }
else else
{ {
contexts = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings: null); contexts = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings);
} }
} }
@ -145,11 +162,12 @@ namespace Microsoft.DotNet.Tools.Compiler
public CompilerCommandApp ShallowCopy() 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. // 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); baseClassOptions[optionTemplate] = _app.Option(optionTemplate, descriptino, CommandOptionType.NoValue);
} }
@ -169,7 +187,7 @@ namespace Microsoft.DotNet.Tools.Compiler
} }
else else
{ {
return new [] { RuntimeValue }; return new[] { RuntimeValue };
} }
} }
} }

View file

@ -27,7 +27,7 @@ Common Commands:
run Compiles and immediately executes a .NET project run Compiles and immediately executes a .NET project
repl Launch an interactive session (read, eval, print, loop) repl Launch an interactive session (read, eval, print, loop)
pack Creates a NuGet package"; pack Creates a NuGet package";
private static readonly string ProductVersion = GetProductVersion(); public static readonly string ProductVersion = GetProductVersion();
private static string GetProductVersion() private static string GetProductVersion()
{ {

View file

@ -17,18 +17,22 @@ namespace Microsoft.DotNet.Tools.Pack
private readonly string _buildBasePath; private readonly string _buildBasePath;
private readonly string _configuration; private readonly string _configuration;
private readonly string _versionSuffix;
private bool SkipBuild => _artifactPathsCalculator.CompiledArtifactsPathSet; private bool SkipBuild => _artifactPathsCalculator.CompiledArtifactsPathSet;
public BuildProjectCommand( public BuildProjectCommand(
Project project, Project project,
ArtifactPathsCalculator artifactPathsCalculator, ArtifactPathsCalculator artifactPathsCalculator,
string buildBasePath, string buildBasePath,
string configuration) string configuration,
string versionSuffix)
{ {
_project = project; _project = project;
_artifactPathsCalculator = artifactPathsCalculator; _artifactPathsCalculator = artifactPathsCalculator;
_buildBasePath = buildBasePath; _buildBasePath = buildBasePath;
_configuration = configuration; _configuration = configuration;
_versionSuffix = versionSuffix;
} }
public int Execute() public int Execute()
@ -44,6 +48,12 @@ namespace Microsoft.DotNet.Tools.Pack
argsBuilder.Add("--configuration"); argsBuilder.Add("--configuration");
argsBuilder.Add($"{_configuration}"); argsBuilder.Add($"{_configuration}");
if (!string.IsNullOrEmpty(_versionSuffix))
{
argsBuilder.Add("--version-suffix");
argsBuilder.Add(_versionSuffix);
}
if (!string.IsNullOrEmpty(_buildBasePath)) if (!string.IsNullOrEmpty(_buildBasePath))
{ {
argsBuilder.Add("--build-base-path"); argsBuilder.Add("--build-base-path");

View file

@ -39,33 +39,31 @@ namespace Microsoft.DotNet.Tools.Compiler
pathValue = Directory.GetCurrentDirectory(); pathValue = Directory.GetCurrentDirectory();
} }
if(!pathValue.EndsWith(Project.FileName)) if (!pathValue.EndsWith(Project.FileName))
{ {
pathValue = Path.Combine(pathValue, Project.FileName); pathValue = Path.Combine(pathValue, Project.FileName);
} }
if(!File.Exists(pathValue)) if (!File.Exists(pathValue))
{ {
Reporter.Error.WriteLine($"Unable to find a project.json in {pathValue}"); Reporter.Error.WriteLine($"Unable to find a project.json in {pathValue}");
return 1; return 1;
} }
// Set defaults based on the environment // Set defaults based on the environment
var settings = new ProjectReaderSettings(); var settings = ProjectReaderSettings.ReadFromEnvironment();
settings.VersionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION"); var versionSuffixValue = versionSuffix.Value();
settings.AssemblyFileVersion = Environment.GetEnvironmentVariable("DOTNET_ASSEMBLY_FILE_VERSION");
if (versionSuffix.HasValue()) if (!string.IsNullOrEmpty(versionSuffixValue))
{ {
settings.VersionSuffix = versionSuffix.Value(); settings.VersionSuffix = versionSuffixValue;
} }
var contexts = ProjectContext.CreateContextForEachFramework(pathValue, settings);
var configValue = configuration.Value() ?? Cli.Utils.Constants.DefaultConfiguration; var configValue = configuration.Value() ?? Cli.Utils.Constants.DefaultConfiguration;
var outputValue = output.Value(); var outputValue = output.Value();
var buildBasePathValue = buildBasePath.Value(); var buildBasePathValue = buildBasePath.Value();
var contexts = ProjectContext.CreateContextForEachFramework(pathValue, settings);
var project = contexts.First().ProjectFile; var project = contexts.First().ProjectFile;
var artifactPathsCalculator = new ArtifactPathsCalculator(project, buildBasePathValue, outputValue, configValue); var artifactPathsCalculator = new ArtifactPathsCalculator(project, buildBasePathValue, outputValue, configValue);
@ -74,7 +72,7 @@ namespace Microsoft.DotNet.Tools.Compiler
int buildResult = 0; int buildResult = 0;
if (!noBuild.HasValue()) if (!noBuild.HasValue())
{ {
var buildProjectCommand = new BuildProjectCommand(project, artifactPathsCalculator, buildBasePathValue, configValue); var buildProjectCommand = new BuildProjectCommand(project, artifactPathsCalculator, buildBasePathValue, configValue, versionSuffixValue);
buildResult = buildProjectCommand.Execute(); buildResult = buildProjectCommand.Execute();
} }
@ -94,6 +92,6 @@ namespace Microsoft.DotNet.Tools.Compiler
#endif #endif
return 1; return 1;
} }
} }
} }
} }

View file

@ -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 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 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 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 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 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); 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.Configuration = configuration.Value() ?? Constants.DefaultConfiguration;
publish.NativeSubdirectories = nativeSubdirectories.HasValue(); publish.NativeSubdirectories = nativeSubdirectories.HasValue();
publish.ProjectPath = projectPath.Value; publish.ProjectPath = projectPath.Value;
publish.VersionSuffix = versionSuffix.Value();
if (string.IsNullOrEmpty(publish.ProjectPath)) if (string.IsNullOrEmpty(publish.ProjectPath))
{ {

View file

@ -28,7 +28,7 @@ namespace Microsoft.DotNet.Tools.Publish
public bool NativeSubdirectories { get; set; } public bool NativeSubdirectories { get; set; }
public NuGetFramework NugetFramework { get; set; } public NuGetFramework NugetFramework { get; set; }
public IEnumerable<ProjectContext> ProjectContexts { get; set; } public IEnumerable<ProjectContext> ProjectContexts { get; set; }
public string VersionSuffix { get; set; }
public int NumberOfProjects { get; private set; } public int NumberOfProjects { get; private set; }
public int NumberOfPublishedProjects { 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="configuration">Debug or Release</param>
/// <param name="nativeSubdirectories"></param> /// <param name="nativeSubdirectories"></param>
/// <returns>Return 0 if successful else return non-zero</returns> /// <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()}"); 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); var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
if (string.IsNullOrEmpty(outputPath)) if (string.IsNullOrEmpty(outputPath))
{ {
outputPath = context.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeOutputPath; outputPath = context.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeOutputPath;
@ -118,6 +118,13 @@ namespace Microsoft.DotNet.Tools.Publish
configuration, configuration,
context.ProjectFile.ProjectDirectory context.ProjectFile.ProjectDirectory
}; };
if (!string.IsNullOrEmpty(VersionSuffix))
{
args.Add("--version-suffix");
args.Add(VersionSuffix);
}
if (!string.IsNullOrEmpty(buildBasePath)) if (!string.IsNullOrEmpty(buildBasePath))
{ {
args.Add("--build-base-path"); args.Add("--build-base-path");
@ -228,7 +235,7 @@ namespace Microsoft.DotNet.Tools.Publish
{ {
Directory.CreateDirectory(destinationDirectory); Directory.CreateDirectory(destinationDirectory);
} }
File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, Path.GetFileName(file.ResolvedPath)), overwrite: true); File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, Path.GetFileName(file.ResolvedPath)), overwrite: true);
} }
} }

View file

@ -16,6 +16,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
private string _buidBasePathDirectory; private string _buidBasePathDirectory;
private string _configuration; private string _configuration;
private string _framework; private string _framework;
private string _versionSuffix;
private bool _noHost; private bool _noHost;
private bool _native; private bool _native;
private string _architecture; private string _architecture;
@ -66,6 +67,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
$"--framework {_framework}"; $"--framework {_framework}";
} }
} }
private string VersionSuffixOption
{
get
{
return _versionSuffix == string.Empty ?
"" :
$"--version-suffix {_versionSuffix}";
}
}
private string NoHostOption private string NoHostOption
{ {
@ -183,6 +194,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
string buidBasePath="", string buidBasePath="",
string configuration="", string configuration="",
string framework="", string framework="",
string versionSuffix="",
bool noHost=false, bool noHost=false,
bool native=false, bool native=false,
string architecture="", string architecture="",
@ -203,6 +215,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
_outputDirectory = output; _outputDirectory = output;
_buidBasePathDirectory = buidBasePath; _buidBasePathDirectory = buidBasePath;
_configuration = configuration; _configuration = configuration;
_versionSuffix = versionSuffix;
_framework = framework; _framework = framework;
_noHost = noHost; _noHost = noHost;
_native = native; _native = native;
@ -238,7 +251,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
private string BuildArgs() 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}";
} }
} }
} }

View file

@ -5,13 +5,16 @@ using Microsoft.DotNet.Cli.Utils;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Collections.Generic;
namespace Microsoft.DotNet.Tools.Test.Utilities namespace Microsoft.DotNet.Tools.Test.Utilities
{ {
public class TestCommand public class TestCommand
{ {
protected string _command; protected string _command;
public Dictionary<string, string> Environment { get; } = new Dictionary<string, string>();
public TestCommand(string command) public TestCommand(string command)
{ {
_command = command; _command = command;
@ -63,9 +66,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
RedirectStandardOutput = true RedirectStandardOutput = true
}; };
foreach (var item in Environment)
{
psi.Environment[item.Key] = item.Value;
}
var process = new Process var process = new Process
{ {
StartInfo = psi StartInfo = psi,
}; };
process.EnableRaisingEvents = true; process.EnableRaisingEvents = true;

View 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.Test.Utilities
{
public static class PeReaderUtils
{
public 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;
}
}
}

View file

@ -1,15 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. // 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. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using FluentAssertions.Common;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using NuGet.Frameworks;
using Xunit; using Xunit;
namespace Microsoft.DotNet.Tools.Builder.Tests namespace Microsoft.DotNet.Tools.Builder.Tests
@ -93,6 +90,44 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
appruntime.Should().Exist().And.HaveFiles(_runtimeFiles); appruntime.Should().Exist().And.HaveFiles(_runtimeFiles);
} }
[Fact]
public void SettingVersionInEnvironment_ShouldStampAssemblyInfoInOutputAssembly()
{
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_ShouldStampAssemblyInfoInOutputAssembly()
{
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] [Fact]
public void ResourceTest() public void ResourceTest()
{ {

View file

@ -3,6 +3,8 @@
using System; using System;
using System.IO; using System.IO;
using FluentAssertions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit; using Xunit;
@ -56,6 +58,25 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests
outputDir.Should().Exist(); outputDir.Should().Exist();
outputDir.Should().HaveFiles(new[] { "TestLibrary.1.0.0.nupkg", "TestLibrary.1.0.0.symbols.nupkg" }); outputDir.Should().HaveFiles(new[] { "TestLibrary.1.0.0.nupkg", "TestLibrary.1.0.0.symbols.nupkg" });
} }
[Fact]
public void SettingVersionSuffixFlag_ShouldStampAssemblyInfoInOutputAssemblyAndPackage()
{
var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithConfiguration")
.WithLockFiles();
var cmd = new PackCommand(Path.Combine(testInstance.TestRoot, Project.FileName), versionSuffix: "85");
cmd.Execute().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");
var outputPackage = Path.Combine(testInstance.TestRoot, "bin", "Debug", "TestLibraryWithConfiguration.1.0.0-85.nupkg");
File.Exists(outputPackage).Should().BeTrue(outputPackage);
}
private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir)
{ {