Skip to content

Commit

Permalink
Make polling use the symbolic link target's LastWriteTime
Browse files Browse the repository at this point in the history
  • Loading branch information
jozkee committed Jul 14, 2021
1 parent f515710 commit 08233ba
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="Microsoft.Extensions.FileProviders.Abstractions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Primitives\ref\Microsoft.Extensions.Primitives.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
<Reference Include="System.Runtime" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<RootNamespace>Microsoft.Extensions.FileProviders</RootNamespace>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
<EnableDefaultItems>true</EnableDefaultItems>
<PackageDescription>Abstractions of files and directories.

Expand All @@ -21,4 +21,9 @@ Microsoft.Extensions.FileProviders.IFileProvider</PackageDescription>
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Primitives\src\Microsoft.Extensions.Primitives.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.Runtime" />
<Reference Include="System.Linq" />
<Reference Include="System.Linq.Expressions" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<UnsupportedOSPlatforms>browser</UnsupportedOSPlatforms>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="Microsoft.Extensions.FileProviders.Physical.cs" />
Expand All @@ -10,4 +10,7 @@
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.FileSystemGlobbing\ref\Microsoft.Extensions.FileSystemGlobbing.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Primitives\ref\Microsoft.Extensions.Primitives.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.IO.FileSystem.Watcher" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.IO;

namespace Microsoft.Extensions.FileProviders.Physical
Expand All @@ -27,5 +28,28 @@ public static bool IsExcluded(FileSystemInfo fileSystemInfo, ExclusionFilters fi

return false;
}

public static FileInfo ResolveFileLinkTarget(string filePath)
#if NETCOREAPP
=> ResolveFileLinkTarget(new FileInfo(filePath));
#else
=> null;
#endif

public static FileInfo ResolveFileLinkTarget(FileInfo fileInfo)
{
#if NETCOREAPP
if (fileInfo.Exists && fileInfo.LinkTarget != null)
{
FileSystemInfo targetInfo = fileInfo.ResolveLinkTarget(returnFinalTarget: true);
if (targetInfo.Exists)
{
return (FileInfo)targetInfo;
}
}
#endif

return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>Microsoft.Extensions.FileProviders</RootNamespace>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableDefaultItems>true</EnableDefaultItems>
<PackageDescription>File provider for physical files for Microsoft.Extensions.FileProviders.</PackageDescription>
Expand All @@ -26,4 +26,15 @@
<PackageReference Include="System.Security.Cryptography.Algorithms" Version="$(SystemSecurityCryptographyAlgorithmsVersion)" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.ComponentModel.Primitives" />
<Reference Include="System.IO.FileSystem.Watcher" />
<Reference Include="System.Linq" />
<Reference Include="System.Linq.Expressions" />
<Reference Include="System.Runtime" />
<Reference Include="System.Security.Cryptography.Algorithms" />
<Reference Include="System.Security.Cryptography.Primitives" />
<Reference Include="System.Threading" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class PollingFileChangeToken : IPollingChangeToken
/// <param name="fileInfo">The <see cref="System.IO.FileInfo"/> to poll</param>
public PollingFileChangeToken(FileInfo fileInfo)
{
_fileInfo = fileInfo;
_fileInfo = FileSystemInfoHelper.ResolveFileLinkTarget(fileInfo) ?? fileInfo;
_previousWriteTimeUtc = GetLastWriteTimeUtc();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ private bool CalculateChanges()
/// <returns>The <see cref="DateTime"/> that the file was last modified.</returns>
protected virtual DateTime GetLastWriteUtc(string path)
{
return File.GetLastWriteTimeUtc(Path.Combine(_directoryInfo.FullName, path));
string filePath = Path.Combine(_directoryInfo.FullName, path);
return FileSystemInfoHelper.ResolveFileLinkTarget(filePath)?.LastWriteTimeUtc ?? File.GetLastWriteTimeUtc(filePath);
}

private static bool ArrayEquals(byte[] previousHash, byte[] currentHash)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,68 @@ public void UsePollingFileWatcher_FileWatcherNotNull_ReturnsFalse()
}
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void UsePollingFileWatcher_UseActivePolling_HasChanged(bool useWildcard)
{
// Arrange
using var root = new DisposableFileSystem();
string fileName = Path.GetRandomFileName();
string filePath = Path.Combine(root.RootPath, fileName);
File.WriteAllText(filePath, "v1.1");

using var provider = new PhysicalFileProvider(root.RootPath) { UsePollingFileWatcher = true, UseActivePolling = true };
IChangeToken token = provider.Watch(useWildcard ? "*" : fileName);
Assert.False(token.HasChanged);

// Act
File.WriteAllText(filePath, "v1.2");
Thread.Sleep(GetTokenPollingInterval(token));

// Assert
Assert.True(token.HasChanged);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void UsePollingFileWatcher_UseActivePolling_HasChanged_SymbolicLink(bool useWildcard)
{
// Arrange
using var rootOfFile = new DisposableFileSystem();
string filePath = Path.Combine(rootOfFile.RootPath, Path.GetRandomFileName());
File.WriteAllText(filePath, "v1.1");

using var rootOfLink = new DisposableFileSystem();
string linkName = Path.GetRandomFileName();
string linkPath = Path.Combine(rootOfLink.RootPath, linkName);
File.CreateSymbolicLink(linkPath, filePath);

using var provider = new PhysicalFileProvider(rootOfLink.RootPath) { UsePollingFileWatcher = true, UseActivePolling = true };
IChangeToken token = provider.Watch(useWildcard ? "*" : linkName);
Assert.False(token.HasChanged);

// Act
File.WriteAllText(filePath, "v1.2");
Thread.Sleep(GetTokenPollingInterval(token));

// Assert
Assert.True(token.HasChanged);
}

private int GetTokenPollingInterval(IChangeToken changeToken)
{
TimeSpan pollingInterval = (changeToken as CompositeChangeToken).ChangeTokens[1] switch
{
PollingWildCardChangeToken wildcardChangeToken => wildcardChangeToken.PollingInterval,
PollingFileChangeToken => PollingFileChangeToken.PollingInterval,
_ => throw new InvalidOperationException()
};

return (int)pollingInterval.TotalMilliseconds;
}

[Fact]
public void CreateFileWatcher_CreatesWatcherWithPollingAndActiveFlags()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="Microsoft.Extensions.FileSystemGlobbing.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.Collections" />
<Reference Include="System.Runtime" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net461</TargetFrameworks>
<EnableDefaultItems>true</EnableDefaultItems>
<PackageDescription>File system globbing to find files matching a specified pattern.</PackageDescription>
</PropertyGroup>
Expand All @@ -10,5 +10,10 @@
<Compile Include="$(CoreLibSharedDir)\System\Numerics\Hashing\HashHelpers.cs"
Link="System\Numerics\Hashing\HashHelpers.cs" />
</ItemGroup>


<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.Collections" />
<Reference Include="System.Linq" />
<Reference Include="System.Runtime" />
</ItemGroup>
</Project>

0 comments on commit 08233ba

Please sign in to comment.