Skip to content

Commit

Permalink
Do not compare separators in paths
Browse files Browse the repository at this point in the history
  • Loading branch information
patriksvensson committed Jul 9, 2024
1 parent 7985900 commit 27d9a6b
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 40 deletions.
44 changes: 22 additions & 22 deletions src/Spectre.IO.Tests/Unit/PathComparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public sealed class TheEqualsMethod
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Same_Asset_Instances_Is_Considered_Equal(bool isCaseSensitive)
public void Same_Asset_Instances_Is_Considered_Equal(bool caseSensitive)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var path = new FilePath("shaders/basic.vert");

// When
Expand All @@ -31,10 +31,10 @@ public void Same_Asset_Instances_Is_Considered_Equal(bool isCaseSensitive)
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Two_Null_Paths_Are_Considered_Equal(bool isCaseSensitive)
public void Two_Null_Paths_Are_Considered_Equal(bool caseSensitive)
{
// Given
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);

// When
var result = comparer.Equals(null, null);
Expand All @@ -46,10 +46,10 @@ public void Two_Null_Paths_Are_Considered_Equal(bool isCaseSensitive)
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Paths_Are_Considered_Inequal_If_Any_Is_Null(bool isCaseSensitive)
public void Paths_Are_Considered_Inequal_If_Any_Is_Null(bool caseSensitive)
{
// Given
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);

// When
var result = comparer.Equals(null, new FilePath("test.txt"));
Expand All @@ -61,10 +61,10 @@ public void Paths_Are_Considered_Inequal_If_Any_Is_Null(bool isCaseSensitive)
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Same_Paths_Are_Considered_Equal(bool isCaseSensitive)
public void Same_Paths_Are_Considered_Equal(bool caseSensitive)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("shaders/basic.vert");

Expand All @@ -76,10 +76,10 @@ public void Same_Paths_Are_Considered_Equal(bool isCaseSensitive)
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Different_Paths_Are_Not_Considered_Equal(bool isCaseSensitive)
public void Different_Paths_Are_Not_Considered_Equal(bool caseSensitive)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("shaders/basic.frag");

Expand All @@ -92,10 +92,10 @@ public void Different_Paths_Are_Not_Considered_Equal(bool isCaseSensitive)
[InlineData(true, false)]
[InlineData(false, true)]
public void Same_Paths_But_Different_Casing_Are_Considered_Equal_Depending_On_Case_Sensitivity(
bool isCaseSensitive, bool expected)
bool caseSensitive, bool expected)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("SHADERS/BASIC.VERT");

Expand All @@ -120,7 +120,7 @@ public void Should_Sort_Paths()

// When
var result = paths
.Order(new PathComparer(isCaseSensitive: false))
.Order(new PathComparer(caseSensitive: false))
.ToList();

// Then
Expand Down Expand Up @@ -149,10 +149,10 @@ public void Should_Throw_If_Other_Path_Is_Null()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Same_Paths_Get_Same_Hash_Code(bool isCaseSensitive)
public void Same_Paths_Get_Same_Hash_Code(bool caseSensitive)
{
// Given
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("shaders/basic.vert");

Expand All @@ -167,10 +167,10 @@ public void Same_Paths_Get_Same_Hash_Code(bool isCaseSensitive)
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Different_Paths_Get_Different_Hash_Codes(bool isCaseSensitive)
public void Different_Paths_Get_Different_Hash_Codes(bool caseSensitive)
{
// Given
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("shaders/basic.frag");

Expand All @@ -186,10 +186,10 @@ public void Different_Paths_Get_Different_Hash_Codes(bool isCaseSensitive)
[InlineData(true, false)]
[InlineData(false, true)]
public void Same_Paths_But_Different_Casing_Get_Same_Hash_Code_Depending_On_Case_Sensitivity(
bool isCaseSensitive, bool expected)
bool caseSensitive, bool expected)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);
var first = new FilePath("shaders/basic.vert");
var second = new FilePath("SHADERS/BASIC.VERT");

Expand Down Expand Up @@ -222,13 +222,13 @@ public sealed class TheIsCaseSensitiveProperty
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Should_Return_Whether_Or_Not_The_Comparer_Is_Case_Sensitive(bool isCaseSensitive)
public void Should_Return_Whether_Or_Not_The_Comparer_Is_Case_Sensitive(bool caseSensitive)
{
// Given, When
var comparer = new PathComparer(isCaseSensitive);
var comparer = new PathComparer(caseSensitive);

// Then
comparer.IsCaseSensitive.ShouldBe(isCaseSensitive);
comparer.IsCaseSensitive.ShouldBe(caseSensitive);
}
}
}
63 changes: 45 additions & 18 deletions src/Spectre.IO/PathComparer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Spectre.IO.Internal;

namespace Spectre.IO;
Expand All @@ -11,7 +12,8 @@ public sealed class PathComparer : IPathComparer
/// <summary>
/// Gets the default path comparer.
/// </summary>
public static PathComparer Default { get; } = new PathComparer(EnvironmentHelper.IsUnix());
public static PathComparer Default { get; }
= new PathComparer(EnvironmentHelper.IsUnix());

/// <summary>
/// Gets a value indicating whether comparison is case sensitive.
Expand All @@ -24,10 +26,10 @@ public sealed class PathComparer : IPathComparer
/// <summary>
/// Initializes a new instance of the <see cref="PathComparer"/> class.
/// </summary>
/// <param name="isCaseSensitive">if set to <c>true</c>, comparison is case sensitive.</param>
public PathComparer(bool isCaseSensitive)
/// <param name="caseSensitive">if set to <c>true</c>, comparison is case sensitive.</param>
public PathComparer(bool caseSensitive)
{
IsCaseSensitive = isCaseSensitive;
IsCaseSensitive = caseSensitive;
}

/// <summary>
Expand All @@ -52,26 +54,39 @@ public int Compare(Path? x, Path? y)
return 0;
}

if (x != null && y == null)
// This might look strange,
// but for some reason, null reference tracking
// does not work correctly otherwise.
if (x == null || y == null)
{
return -1;
if (x != null && y == null)
{
return -1;
}

return 1;
}

if (x == null && y != null)
if (x.Segments.Count != y.Segments.Count)
{
return 1;
return x.Segments.Count
.CompareTo(y.Segments.Count);
}

if (IsCaseSensitive)
var comparer = IsCaseSensitive
? StringComparer.Ordinal
: StringComparer.OrdinalIgnoreCase;

foreach (var (segmentX, segmentY) in x.Segments.Zip(y.Segments))
{
return StringComparer.Ordinal.Compare(
x!.FullPath,
y!.FullPath);
var sort = comparer.Compare(segmentX, segmentY);
if (sort != 0)
{
return sort;
}
}

return StringComparer.OrdinalIgnoreCase.Compare(
x!.FullPath,
y!.FullPath);
return 0;
}

/// <inheritdoc/>
Expand All @@ -87,12 +102,24 @@ public bool Equals(Path? x, Path? y)
return false;
}

if (IsCaseSensitive)
if (x.Segments.Count != y.Segments.Count)
{
return false;
}

var comparer = IsCaseSensitive
? StringComparer.Ordinal
: StringComparer.OrdinalIgnoreCase;

foreach (var (segmentX, segmentY) in x.Segments.Zip(y.Segments))
{
return x.FullPath.Equals(y.FullPath, StringComparison.Ordinal);
if (!comparer.Equals(segmentX, segmentY))
{
return false;
}
}

return x.FullPath.Equals(y.FullPath, StringComparison.OrdinalIgnoreCase);
return true;
}

/// <inheritdoc/>
Expand Down

0 comments on commit 27d9a6b

Please sign in to comment.