// 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 Microsoft.Build.Construction;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Microsoft.DotNet.Cli.Build
{
public class GenerateNuGetPackagesArchiveVersion : Task
public GenerateNuGetPackagesArchiveVersion()
}
[Required]
public string ToolPath { get; set; }
[Output]
public String Version { get; set; }
private static string[][] _templatesAndArgs = new string[][]
new string[] { "console", "" },
};
public override bool Execute()
var dataToHash = string.Empty;
foreach (var newArgs in _templatesAndArgs)
var targetDir = Path.GetTempFileName();
File.Delete(targetDir);
Directory.CreateDirectory(targetDir);
var outputDir = Path.Combine(targetDir, newArgs[0]);
Directory.CreateDirectory(outputDir);
var newTask = new DotNetNew
ToolPath = ToolPath,
TemplateType = newArgs[0],
TemplateArgs = newArgs[1] + $" --debug:ephemeral-hive -n TempProject -o \"{outputDir}\"",
HostObject = HostObject,
BuildEngine = BuildEngine
newTask.Execute();
var templatePath = Path.Combine(outputDir, "TempProject.csproj");
var rootElement = ProjectRootElement.Open(templatePath);
var packageRefs = rootElement.Items.Where(i => i.ItemType == "PackageReference").ToList();
foreach (var packageRef in packageRefs)
dataToHash += $"{packageRef.Include},";
if (packageRef.HasMetadata)
foreach (var metadata in packageRef.Metadata)
dataToHash += $"{metadata.Name}={metadata.Value};";
var frameworkVersion = rootElement.Properties.LastOrDefault(p => p.Name == "RuntimeFrameworkVersion");
if (frameworkVersion != null)
dataToHash += $"RuntimeFrameworkVersion={frameworkVersion.Value}";
Directory.Delete(targetDir, true);
Log.LogMessage($"NuGet Packages Archive Data To Hash: '{dataToHash}'");
var sha256 = SHA256.Create();
var hashBytes = sha256.ComputeHash(Encoding.Unicode.GetBytes(dataToHash));
Version = GetHashString(hashBytes);
Log.LogMessage($"NuGet Packages Archive Version: '{Version}'");
return true;
private string GetHashString(byte[] hashBytes)
StringBuilder builder = new StringBuilder(hashBytes.Length * 2);
foreach (var b in hashBytes)
builder.AppendFormat("{0:x2}", b);
return builder.ToString();