This repository was archived by the owner on Aug 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCIBuildDescriptor.cs
More file actions
137 lines (123 loc) · 5.54 KB
/
CIBuildDescriptor.cs
File metadata and controls
137 lines (123 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSemVer
{
/// <summary>
/// Encapsulates CSemVer-CI suffix formatting.
/// </summary>
public class CIBuildDescriptor
{
/// <summary>
/// Defines the maximal build index.
/// This is required to be able to pad it with a constant number of '0'.
/// </summary>
public const int MaxShortFormIndex = 9999;
int _buildIndex;
/// <summary>
/// Gets or sets the build index. Must be greater or equal to 0.
/// To be valid for NuGetV2, it must not exceed <see cref="MaxShortFormIndex"/>.
/// </summary>
public int BuildIndex
{
get { return _buildIndex; }
set
{
if( _buildIndex < 0 ) throw new ArgumentException();
_buildIndex = value;
}
}
/// <summary>
/// Gets or set the branch name to use.
/// When null or empty, this descriptor is not applicable.
/// </summary>
public string BranchName { get; set; }
/// <summary>
/// Gets whether this descriptor can be applied.
/// </summary>
public bool IsValid
{
get { return _buildIndex >= 0 && !string.IsNullOrWhiteSpace( BranchName ); }
}
/// <summary>
/// Gets whether this descriptor can be applied for NuGetV2 special name case.
/// </summary>
public bool IsValidForShortForm
{
get { return IsValid && _buildIndex <= MaxShortFormIndex && BranchName.Length <= 8; }
}
/// <summary>
/// Overridden to return "ci.<see cref="BuildIndex"/>.<see cref="BranchName"/>" when <see cref="IsValid"/> is true,
/// the empty string otherwise.
/// </summary>
/// <returns>The long form like "ci.16.develop".</returns>
public override string ToString()
{
return IsValid ? string.Format( "ci.{0}.{1}", BuildIndex, BranchName ) : string.Empty;
}
/// <summary>
/// When <see cref="IsValidForShortForm"/> is true, returns "<see cref="BuildIndex"/>-<see cref="BranchName"/>" where
/// the index is padded with 0, the empty string otherwise.
/// </summary>
/// <returns>The short form like "0016-develop".</returns>
public string ToStringForShortForm()
{
Debug.Assert( MaxShortFormIndex.ToString().Length == 4 );
return IsValid ? string.Format( "{0:0000}-{1}", BuildIndex, BranchName ) : string.Empty;
}
/// <summary>
/// Creates the ZeroTimed short form version string. It uses a base 36 alphabet (case insensitive) and consider the nunber
/// of seconds from 1st of january 2015: this fits into 7 characters.
/// </summary>
/// <param name="ciBuildName">The BuildName string (typically "develop"). Must not be null, empty or longer than 8 characters.</param>
/// <param name="timeRelease">The utc date time of the release.</param>
/// <returns>A Short form version string like "O.O.O--009iJKg-develop".</returns>
public static string CreateShortFormZeroTimed( string ciBuildName, DateTime timeRelease )
{
CheckCIBuildName( ciBuildName, true );
DateTime baseTime = new DateTime( 2015, 1, 1, 0, 0, 0, DateTimeKind.Utc );
if( timeRelease < baseTime ) throw new ArgumentException( $"Must be at least {baseTime}.", nameof( timeRelease ) );
TimeSpan delta200 = timeRelease - baseTime;
Debug.Assert( Math.Log( 1000 * 366 * 24 * 60 * (long)60, 36 ) < 7, "Using Base36: 1000 years in seconds on 7 chars!" );
long second = (long)delta200.TotalSeconds;
string b36 = ToBase36( second );
string ver = new string( '0', 7 - b36.Length ) + b36;
return string.Format( "0.0.0--{0}-{1}", ver, ciBuildName );
}
/// <summary>
/// Creates the ZeroTimed SemVer version string.
/// </summary>
/// <param name="ciBuildName">The BuildName string (typically "develop").</param>
/// <param name="timeRelease">The utc date time of the release.</param>
/// <returns>A SemVer version string like "O.O.O--ci.2018-07-27T09-45-28-34.develop".</returns>
public static string CreateSemVerZeroTimed( string ciBuildName, DateTime timeRelease )
{
CheckCIBuildName( ciBuildName, false );
return string.Format( "0.0.0--ci.{0:yyyy-MM-ddTHH-mm-ss-ff}.{1}", timeRelease, ciBuildName );
}
static void CheckCIBuildName( string ciBuildName, bool shortForm )
{
if( string.IsNullOrWhiteSpace( ciBuildName ) ) throw new ArgumentException( "Must not be null, empty or whitespace.", nameof( ciBuildName ) );
if( shortForm && ciBuildName.Length > 8 ) throw new ArgumentException( "Must not be longer than 8 characters", nameof( ciBuildName ) );
}
static string ToBase36( long number )
{
// Naïve implementation that does the job.
var alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
Debug.Assert( alphabet.Length == 36 );
var n = number;
long basis = 36;
var ret = "";
while( n > 0 )
{
long temp = n % basis;
ret = alphabet[(int)temp] + ret;
n = (n / basis);
}
return ret;
}
}
}