Skip to content
Open
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
6 changes: 4 additions & 2 deletions src/FileProviderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.FileProviders;

Expand Down Expand Up @@ -26,7 +27,8 @@ public static byte[] ReadAsBytes(this IFileInfo file)
/// <summary>Reads the entire file into a byte array.</summary>
/// <param name="file">The file to read.</param>
/// <returns>(awaitable) The contents of the file as a byte array.</returns>
public static async Task<byte[]> ReadAsBytesAsync(this IFileInfo file)
/// <param name="cancel">Cancellation token.</param>
public static async Task<byte[]> ReadAsBytesAsync(this IFileInfo file, CancellationToken cancel = default)
{
using var stream = file.CreateReadStream();
if (stream is MemoryStream ms)
Expand All @@ -35,7 +37,7 @@ public static async Task<byte[]> ReadAsBytesAsync(this IFileInfo file)
}

using var output = new MemoryStream();
await stream.CopyToAsync(output);
await stream.CopyToAsync(output, 81920, cancel);
return output.ToArray();
}

Expand Down
2 changes: 1 addition & 1 deletion src/InMemory/InMemoryFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public InMemoryFileInfo(string name, string content, DateTimeOffset? lastModifie
/// <inheritdoc />
public string? Name { get; }
/// <inheritdoc />
public DateTimeOffset LastModified { get; }
public DateTimeOffset LastModified { get; internal set; }

/// <inheritdoc />
public bool Exists => true;
Expand Down
18 changes: 18 additions & 0 deletions src/InMemory/InMemoryFileProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,22 @@ private static string NormalizePath(string path)
if (path == null) { throw new ArgumentNullException(nameof(path)); }
return path.Replace("\\", "/").TrimStart('/');
}

/// <inheritdoc />
public void ChangeLastModified(string path, DateTimeOffset lastModified)
{
var fileInfo = this[path];
if (fileInfo is null)
{
throw new FileNotFoundException("File not found", path);
}

if (fileInfo is InMemoryFileInfo inMemoryFileInfo)
{
inMemoryFileInfo.LastModified = lastModified;
return;
}

throw new InvalidOperationException("Cannot change last modified on a non-in-memory file");
}
}
2 changes: 1 addition & 1 deletion src/Mirality.FileProviders.InMemory.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>10</LangVersion>
<VersionPrefix>6.2.1</VersionPrefix>
<Nullable>enable</Nullable>
Expand Down
13 changes: 10 additions & 3 deletions src/WritableFileProvider.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Microsoft.Extensions.FileProviders;
using System;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.FileProviders;

namespace Mirality.FileProviders;

Expand All @@ -19,6 +19,13 @@ public interface IWritableFileProvider : IFileProvider
/// <remarks>It's not an error if the file already does not exist.</remarks>
/// <param name="path">The full relative file path.</param>
void Delete(string path);

/// <summary>
/// Changes the last modified time of a file.
/// </summary>
/// <param name="path">The full relative file path.</param>
/// <param name="lastModified">When the file was last modified.</param>
void ChangeLastModified(string path, DateTimeOffset lastModified);
}

/// <summary>An <see cref="IWritableFileProvider"/> that provides synchronous write operations.</summary>
Expand Down
15 changes: 11 additions & 4 deletions src/WritablePhysicalFileProvider.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;

namespace Mirality.FileProviders;

Expand Down Expand Up @@ -138,4 +138,11 @@ public void Delete(string path)

file.Delete();
}

/// <inheritdoc />
public void ChangeLastModified(string path, DateTimeOffset lastModified)
{
var file = GetPhysicalFileInfo(path);
file.LastWriteTimeUtc = lastModified.UtcDateTime;
}
}
15 changes: 15 additions & 0 deletions tests/InMemoryFileProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ public void ExistingFiles()
});
}

[Test]
public void ChangeLastModified()
{
var provider = new InMemoryFileProvider();
var initialTimestamp = new DateTimeOffset(2021, 12, 25, 12, 34, 56, TimeSpan.Zero);
var updatedTimestamp = new DateTimeOffset(2022, 1, 2, 3, 4, 5, TimeSpan.Zero);

provider.Write("test.txt", "hello world", initialTimestamp);
provider.ChangeLastModified("test.txt", updatedTimestamp);

var file = provider.GetFileInfo("test.txt");
Assert.That(file.Exists);
Assert.That(file.LastModified, Is.EqualTo(updatedTimestamp));
}

[Test]
public void FileInfoForDirectories()
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Mirality.FileProviders.InMemory.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net6.0</TargetFrameworks>
<TargetFrameworks>net48;net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
19 changes: 17 additions & 2 deletions tests/WritablePhysicalFileProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public async Task WriteBytesAsyncGeneric()

var timestamp = new DateTimeOffset(2021, 12, 25, 12, 34, 56, TimeSpan.Zero);
var bytes = new byte[] { 1, 2, 3, 4, 5, 6 };
var file = await ((IWritableFileProvider) provider).WriteAsync("test.bin", bytes, timestamp);
var file = await ((IWritableFileProvider)provider).WriteAsync("test.bin", bytes, timestamp);

Assert.That(file.Exists);
Assert.That(_PhysicalFileProvider.GetFileInfo("test.bin").Exists);
Expand All @@ -176,13 +176,28 @@ public async Task WriteTextAsyncGeneric()
var provider = new WritablePhysicalFileProvider(_TestDirectory, _PhysicalFileProvider);

var timestamp = new DateTimeOffset(2021, 12, 25, 12, 34, 56, TimeSpan.Zero);
var file = await ((IWritableFileProvider) provider).WriteAsync("test.txt", "hello world", timestamp);
var file = await ((IWritableFileProvider)provider).WriteAsync("test.txt", "hello world", timestamp);

Assert.That(file.Exists);
Assert.That(_PhysicalFileProvider.GetFileInfo("test.txt").Exists);
Assert.That(_PhysicalFileProvider.GetFileInfo("test.txt").LastModified, Is.EqualTo(timestamp));
}

[Test]
public async Task ChangeLastModified()
{
var provider = new WritablePhysicalFileProvider(_TestDirectory, _PhysicalFileProvider);
var initialTimestamp = new DateTimeOffset(2021, 12, 25, 12, 34, 56, TimeSpan.Zero);
var updatedTimestamp = new DateTimeOffset(2022, 1, 2, 3, 4, 5, TimeSpan.Zero);

await provider.WriteAsync("test.txt", "hello world", initialTimestamp);
provider.ChangeLastModified("test.txt", updatedTimestamp);

var file = _PhysicalFileProvider.GetFileInfo("test.txt");
Assert.That(file.Exists);
Assert.That(file.LastModified, Is.InRange(updatedTimestamp.AddSeconds(-1), updatedTimestamp.AddSeconds(1))); // for some reason this is one second off.
}

[Test]
public void Delete()
{
Expand Down