-
-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Clean-up Project GUID generation code (#261)
- Loading branch information
Showing
5 changed files
with
75 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#nullable enable | ||
|
||
using System.Security.Cryptography; | ||
|
||
namespace Buildalyzer; | ||
|
||
/// <summary>Generates Project <see cref="Guid"/>'s.</summary> | ||
/// <remarks> | ||
/// See: https://datatracker.ietf.org/doc/html/rfc4122. | ||
/// </remarks> | ||
internal static class ProjectGuid | ||
{ | ||
/// <summary>The namespace for URL's.</summary> | ||
private static readonly Guid UrlNamespace = Guid.Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); | ||
|
||
/// <summary>Generates a <see cref="Guid"/> based on the <see cref="SHA1"/> hash of the name.</summary> | ||
public static Guid Create(string? name) | ||
{ | ||
byte[] guid = Hash(Encoding.UTF8.GetBytes(name ?? string.Empty)); | ||
|
||
// set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the appropriate 4-bit version number from Section 4.1.3 (step 8) | ||
guid[6] = (byte)((guid[6] & 0x0F) | 0x50); | ||
|
||
// set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively (step 10) | ||
guid[8] = (byte)((guid[8] & 0x3F) | 0x80); | ||
|
||
// convert the resulting UUID to local byte order (step 13) | ||
SwapBytes(guid); | ||
return new Guid(guid); | ||
} | ||
|
||
/// <summary>Generates a <see cref="SHA1"/> hash.</summary> | ||
[Pure] | ||
private static byte[] Hash(byte[] bytes) | ||
{ | ||
// convert the namespace UUID to network order (step 3) | ||
var ns = UrlNamespace.ToByteArray(); | ||
Check warning on line 37 in src/Buildalyzer/ProjectGuid.cs
|
||
SwapBytes(ns); | ||
|
||
// compute the hash of the name space ID concatenated with the name (step 4) | ||
using var sha1 = SHA1.Create(); | ||
Check warning on line 41 in src/Buildalyzer/ProjectGuid.cs
|
||
sha1.TransformBlock(ns, 0, ns.Length, null, 0); | ||
sha1.TransformFinalBlock(bytes, 0, bytes.Length); | ||
return sha1.Hash![..16]; | ||
} | ||
|
||
/// <summary>Converts a GUID (expressed as a byte array) to/from network order (MSB-first).</summary> | ||
private static void SwapBytes(byte[] bytes) | ||
{ | ||
Swap(bytes, 0, 3); | ||
Swap(bytes, 1, 2); | ||
Swap(bytes, 4, 5); | ||
Swap(bytes, 6, 7); | ||
|
||
static void Swap(byte[] bs, int l, int r) => (bs[r], bs[l]) = (bs[l], bs[r]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#nullable enable | ||
|
||
using Buildalyzer; | ||
using FluentAssertions; | ||
|
||
namespace Project_GUID_specs; | ||
|
||
public class Creates | ||
{ | ||
[TestCase(null, /*....*/ "1b4db7eb-4057-5ddf-91e0-36dec72071f5")] | ||
[TestCase("", /*......*/ "1b4db7eb-4057-5ddf-91e0-36dec72071f5")] | ||
[TestCase("ABCDEFGHIJK", "2a738916-9f0a-5c81-a8fa-cc64ba606458")] | ||
[TestCase("Buildalyzer", "74397281-1b33-5316-aad1-c7ef52552d75")] | ||
public void SHA1_based_GUID(string? name, Guid projectId) | ||
=> ProjectGuid.Create(name).Should().Be(projectId); | ||
} |