Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean-up Project GUID generation code #261

Merged
merged 2 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Buildalyzer/AnalyzerResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
if (string.IsNullOrEmpty(projectGuid) || !Guid.TryParse(projectGuid, out _projectGuid))
{
_projectGuid = analyzer == null
? GuidUtility.Create(GuidUtility.UrlNamespace, ProjectFilePath)
? Buildalyzer.ProjectGuid.Create(ProjectFilePath)
: analyzer.ProjectGuid;
}
}
Expand Down Expand Up @@ -156,13 +156,13 @@
internal void ProcessProject(PropertiesAndItems propertiesAndItems)
{
// Add properties
foreach (var entry in propertiesAndItems.Properties)

Check warning on line 159 in src/Buildalyzer/AnalyzerResult.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1009)

Check warning on line 159 in src/Buildalyzer/AnalyzerResult.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1009)
{
_properties[entry.Key] = entry.StringValue;
}

// Add items
foreach (var items in propertiesAndItems.Items)

Check warning on line 165 in src/Buildalyzer/AnalyzerResult.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1009)

Check warning on line 165 in src/Buildalyzer/AnalyzerResult.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1009)
{
_items[items.Key] = items.Values.Select(task => new ProjectItem(task)).ToArray();
}
Expand Down
111 changes: 0 additions & 111 deletions src/Buildalyzer/GuidUtility.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Buildalyzer/ProjectAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ internal ProjectAnalyzer(AnalyzerManager manager, string projectFilePath, Projec

// Get (or create) a project GUID
ProjectGuid = projectInSolution == null
? GuidUtility.Create(GuidUtility.UrlNamespace, ProjectFile.Name)
? Buildalyzer.ProjectGuid.Create(ProjectFile.Name)
: Guid.Parse(projectInSolution.ProjectGuid);

// Set the solution directory global property
Expand Down
57 changes: 57 additions & 0 deletions src/Buildalyzer/ProjectGuid.cs
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

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)

Check warning on line 37 in src/Buildalyzer/ProjectGuid.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)

Check warning on line 37 in src/Buildalyzer/ProjectGuid.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)
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

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)

Check warning on line 41 in src/Buildalyzer/ProjectGuid.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)

Check warning on line 41 in src/Buildalyzer/ProjectGuid.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

([deprecated] Use RCS1264 instead) Use explicit type instead of 'var' (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1008)
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]);
}
}
16 changes: 16 additions & 0 deletions tests/Buildalyzer.Tests/Project_GUID_specs.cs
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);
}
Loading