|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Build.Framework;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Microsoft.DotNet.Build.Tasks.Installers
{
public sealed class GenerateCurrentVersion : BuildTask
{
/// <summary>
/// The passed in date that will be used to generate a version. (yyyy-MM-dd format)
/// </summary>
[Required]
public string SeedDate { get; set; }
/// <summary>
/// Optional parameter containing the Official Build Id. We'll use this to get the revision number out and use it as BuildNumberMinor.
/// </summary>
public string OfficialBuildId { get; set; }
/// <summary>
/// Optional parameter that sets the Padding for the version number. Must be 5 or bigger.
/// </summary>
public int Padding { get; set; }
/// <summary>
/// If basing off of internal builds version format is not required, this optional parameter lets you pass in a comparison date.
/// </summary>
public string ComparisonDate { get; set; }
/// <summary>
/// The Major Version that will be produced given a SeedDate.
/// </summary>
[Output]
public string GeneratedVersion { get; set; }
/// <summary>
/// The Revision number that will be produced from the BuildNumber.
/// </summary>
[Output]
public string GeneratedRevision { get; set; }
private const string DateFormat = "yyyy-MM-dd";
private const string LastModifiedTimeDateFormat = "yyyy-MM-dd HH:mm:ss.FFFFFFF";
private readonly CultureInfo enUS = new CultureInfo("en-US");
public override bool Execute()
{
// If OfficialBuildId is passed in, then use that to calculate the version and revision.
if (string.IsNullOrEmpty(OfficialBuildId))
{
GeneratedRevision = "0";
}
else
{
bool success = SetVersionAndRevisionFromBuildId(OfficialBuildId);
return success;
}
// Calculating GeneratedVersion
if (Padding == 0)
{
Padding = 5;
}
else if (Padding < 5)
{
Log.LogWarning("The specified Padding '{0}' has to be equal to or greater than 5. Using 5 as a default now.", Padding);
Padding = 5;
}
DateTime date;
GeneratedVersion = string.Empty;
if (!(DateTime.TryParseExact(SeedDate, DateFormat, enUS, DateTimeStyles.AssumeLocal, out date)))
{
// Check if the timestamp matches the LastModifiedTimeDateFormat
if (!(DateTime.TryParseExact(SeedDate, LastModifiedTimeDateFormat, enUS, DateTimeStyles.AssumeLocal, out date)))
{
Log.LogError("The seed date '{0}' is not valid. Please specify a date in the short format.({1})", SeedDate, DateFormat);
return false;
}
}
//Convert Date to UTC to converge
date = date.ToUniversalTime();
GeneratedVersion = GetCurrentVersionForDate(date, ComparisonDate);
if (string.IsNullOrEmpty(GeneratedVersion))
{
Log.LogError("The date '{0}' is not valid. Please pass in a date after {1}.", SeedDate, ComparisonDate);
return false;
}
return true;
}
public bool SetVersionAndRevisionFromBuildId(string buildId)
{
Regex regex = new Regex(@"(\d{8})[\-\.](\d+)$");
string dateFormat = "yyyyMMdd";
Match match = regex.Match(buildId);
if (match.Success && match.Groups.Count > 2)
{
DateTime buildIdDate;
if (!DateTime.TryParseExact(match.Groups[1].Value, dateFormat, enUS, DateTimeStyles.AssumeLocal, out buildIdDate))
{
Log.LogError("The OfficialBuildId doesn't follow the expected({0}.rr) format: '{1}'", dateFormat, match.Groups[1].Value);
return false;
}
buildIdDate = buildIdDate.ToUniversalTime();
GeneratedVersion = GetCurrentVersionForDate(buildIdDate, ComparisonDate);
GeneratedRevision = match.Groups[2].Value;
return true;
}
Log.LogError("Error: Invalid OfficialBuildId was passed: '{0}'", buildId);
return false;
}
public string GetCurrentVersionForDate(DateTime seedDate, string comparisonDate)
{
DateTime compareDate;
if (string.IsNullOrEmpty(comparisonDate))
{
/*
* We need to ensure that our build numbers are higher that what we used to ship internal builds so this date
* will make that possible.
*/
compareDate = new DateTime(1996, 4, 1, 0, 0, 0, DateTimeKind.Utc);
}
else
{
bool isValidDate = DateTime.TryParseExact(comparisonDate, DateFormat, enUS, DateTimeStyles.AssumeLocal, out compareDate);
if (!isValidDate)
{
Log.LogError("The comparison date '{0}' is not valid. Please specify a date in the short format.({1})", comparisonDate, DateFormat);
}
//Convert to UTC to converge
compareDate = compareDate.ToUniversalTime();
}
int months = (seedDate.Year - compareDate.Year) * 12 + seedDate.Month - compareDate.Month;
if (months > 0) //only allow dates after comparedate
{
return string.Format("{0}{1}", months.ToString("D" + (Padding - 2)), seedDate.Day.ToString("D2"));
}
return string.Empty;
}
}
}
|