Replace legacy FTP dependency and add CI

This commit is contained in:
2026-02-28 17:31:19 +01:00
parent 654bcd8a1b
commit c6bc74c265
6 changed files with 53 additions and 59 deletions

20
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Docker Build
on:
push:
branches:
- master
- main
- codex/**
pull_request:
jobs:
docker-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build test image
run: docker build --target test -t virtualfs:test .

View File

@@ -8,6 +8,7 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject> <IsTestProject>true</IsTestProject>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport> <TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
<NoWarn>$(NoWarn);MTP0001</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -46,6 +46,16 @@ namespace VirtualFS.EmbeddedResource
/// <summary>Gets the assembly on which file system operates.</summary> /// <summary>Gets the assembly on which file system operates.</summary>
public Assembly Assembly { get; private set; } public Assembly Assembly { get; private set; }
private string AssemblyLocation
{
get { return string.IsNullOrEmpty(Assembly.Location) ? null : Assembly.Location; }
}
private DateTime AssemblyTimestamp(Func<System.IO.FileInfo, DateTime> selector)
{
return string.IsNullOrEmpty(AssemblyLocation) ? DateTime.UtcNow : selector(new System.IO.FileInfo(AssemblyLocation));
}
/// <summary>Initializes a new instance of the <see cref="EmbeddedResourceFileSystem"/> class.</summary> /// <summary>Initializes a new instance of the <see cref="EmbeddedResourceFileSystem"/> class.</summary>
/// <param name="assembly">The assembly.</param> /// <param name="assembly">The assembly.</param>
/// <param name="rootNamespace">The root namespace.</param> /// <param name="rootNamespace">The root namespace.</param>
@@ -55,8 +65,6 @@ namespace VirtualFS.EmbeddedResource
{ {
Assembly = assembly; Assembly = assembly;
var fi = new System.IO.FileInfo(Uri.UnescapeDataString(new UriBuilder(Assembly.CodeBase).Path));
_pathToResource = Assembly.GetManifestResourceNames() _pathToResource = Assembly.GetManifestResourceNames()
.Where(x => (string.IsNullOrEmpty(rootNamespace) || x.StartsWith(rootNamespace)) && (filter == null || filter.IsMatch(x))) .Where(x => (string.IsNullOrEmpty(rootNamespace) || x.StartsWith(rootNamespace)) && (filter == null || filter.IsMatch(x)))
.Select(x => new File() .Select(x => new File()
@@ -65,9 +73,9 @@ namespace VirtualFS.EmbeddedResource
IsReadOnly = IsReadOnly, IsReadOnly = IsReadOnly,
Path = ResourceToPath(rootNamespace, x), Path = ResourceToPath(rootNamespace, x),
FileSystem = this, FileSystem = this,
CreationTime = fi.CreationTimeUtc, CreationTime = AssemblyTimestamp(fi => fi.CreationTimeUtc),
LastAccessTime = fi.LastAccessTime, LastAccessTime = AssemblyTimestamp(fi => fi.LastAccessTimeUtc),
LastWriteTime = fi.LastWriteTime, LastWriteTime = AssemblyTimestamp(fi => fi.LastWriteTimeUtc),
Size = 0, Size = 0,
}) })
.ToDictionary( .ToDictionary(
@@ -86,9 +94,9 @@ namespace VirtualFS.EmbeddedResource
IsReadOnly = IsReadOnly, IsReadOnly = IsReadOnly,
Path = p, Path = p,
FileSystem = this, FileSystem = this,
CreationTime = fi.CreationTimeUtc, CreationTime = AssemblyTimestamp(fi => fi.CreationTimeUtc),
LastAccessTime = fi.LastAccessTime, LastAccessTime = AssemblyTimestamp(fi => fi.LastAccessTimeUtc),
LastWriteTime = fi.LastWriteTime, LastWriteTime = AssemblyTimestamp(fi => fi.LastWriteTimeUtc),
})); }));
// Ugly but it works (fix this - performance) // Ugly but it works (fix this - performance)
@@ -143,17 +151,15 @@ namespace VirtualFS.EmbeddedResource
if (!ret && path.IsDirectory && _pathToResource.Keys.Any(x => x.IsParentOf(path))) if (!ret && path.IsDirectory && _pathToResource.Keys.Any(x => x.IsParentOf(path)))
{ {
var fi = new System.IO.FileInfo(Uri.UnescapeDataString(new UriBuilder(Assembly.CodeBase).Path));
_pathToResource.Add(path, new Directory() _pathToResource.Add(path, new Directory()
{ {
Data = null, Data = null,
IsReadOnly = IsReadOnly, IsReadOnly = IsReadOnly,
Path = path, Path = path,
FileSystem = this, FileSystem = this,
CreationTime = fi.CreationTimeUtc, CreationTime = AssemblyTimestamp(fi => fi.CreationTimeUtc),
LastAccessTime = fi.LastAccessTime, LastAccessTime = AssemblyTimestamp(fi => fi.LastAccessTimeUtc),
LastWriteTime = fi.LastWriteTime, LastWriteTime = AssemblyTimestamp(fi => fi.LastWriteTimeUtc),
}); });
ret = true; ret = true;
@@ -182,7 +188,7 @@ namespace VirtualFS.EmbeddedResource
/// should return null if real path can't be determined.</remarks> /// should return null if real path can't be determined.</remarks>
public override string EntryRealPath(Path path) public override string EntryRealPath(Path path)
{ {
return Uri.UnescapeDataString(new UriBuilder(Assembly.CodeBase).Path); return AssemblyLocation;
} }
/// <summary>Get entries located under given path.</summary> /// <summary>Get entries located under given path.</summary>

View File

@@ -30,8 +30,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.FtpClient;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentFTP;
using VirtualFS.Base; using VirtualFS.Base;
using VirtualFS.Implementation; using VirtualFS.Implementation;
@@ -157,11 +157,11 @@ namespace VirtualFS.Physical
{ {
foreach (FtpListItem item in conn foreach (FtpListItem item in conn
.GetListing(GetFtpPath(path), .GetListing(GetFtpPath(path),
FtpListOption.Modify | FtpListOption.Size | FtpListOption.DerefLinks | FtpListOption.AllFiles)) FtpListOption.Modify | FtpListOption.Size | FtpListOption.AllFiles))
{ {
switch (item.Type) switch (item.Type)
{ {
case FtpFileSystemObjectType.File: case FtpObjectType.File:
result.Add(new File() result.Add(new File()
{ {
IsReadOnly = IsReadOnly, IsReadOnly = IsReadOnly,
@@ -174,7 +174,7 @@ namespace VirtualFS.Physical
}); });
break; break;
case FtpFileSystemObjectType.Directory: case FtpObjectType.Directory:
result.Add(new Directory() result.Add(new Directory()
{ {
IsReadOnly = IsReadOnly, IsReadOnly = IsReadOnly,
@@ -185,41 +185,6 @@ namespace VirtualFS.Physical
LastAccessTime = item.Modified, LastAccessTime = item.Modified,
}); });
break; break;
case FtpFileSystemObjectType.Link:
if (item.LinkObject != null)
{
switch (item.LinkObject.Type)
{
case FtpFileSystemObjectType.File:
result.Add(new File()
{
IsReadOnly = IsReadOnly,
Path = path + item.Name,
FileSystem = this,
CreationTime = item.LinkObject.Created,
LastWriteTime = item.LinkObject.Modified,
LastAccessTime = item.LinkObject.Modified,
Size = item.LinkObject.Size,
});
break;
case FtpFileSystemObjectType.Directory:
result.Add(new Directory()
{
IsReadOnly = IsReadOnly,
Path = string.Concat(path, item.Name.TrimEnd('/'), "/"),
FileSystem = this,
CreationTime = item.LinkObject.Created,
LastWriteTime = item.LinkObject.Modified,
LastAccessTime = item.LinkObject.Modified,
});
break;
}
}
break;
} }
} }
} }
@@ -366,11 +331,11 @@ namespace VirtualFS.Physical
private FtpClient GetConnection() private FtpClient GetConnection()
{ {
FtpClient conn = new FtpClient(); FtpClient conn = new FtpClient();
conn.DataConnectionType = ConnectionType;
conn.Host = _ftpServer; conn.Host = _ftpServer;
conn.Port = _ftpServerPort; conn.Port = _ftpServerPort;
conn.Credentials = new NetworkCredential(_userName, _password); conn.Credentials = new NetworkCredential(_userName, _password);
conn.Config.DataConnectionType = ConnectionType;
conn.Connect();
return conn; return conn;
} }

View File

@@ -36,6 +36,7 @@ using VirtualFS.Implementation;
namespace VirtualFS.Physical namespace VirtualFS.Physical
{ {
#pragma warning disable SYSLIB0014
/// <summary>Ftp file system implementation.</summary> /// <summary>Ftp file system implementation.</summary>
/// <remarks>This is very, very simple implementation /// <remarks>This is very, very simple implementation
/// of a FTP file system. Use this when regular FTP won't do the job.</remarks> /// of a FTP file system. Use this when regular FTP won't do the job.</remarks>
@@ -373,4 +374,5 @@ namespace VirtualFS.Physical
} }
} }
} }
#pragma warning restore SYSLIB0014
} }

View File

@@ -18,9 +18,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="FluentFTP" Version="53.0.2" />
<PackageReference Include="SharpZipLib" Version="1.4.2" /> <PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="SSH.NET" Version="2024.0.0" /> <PackageReference Include="SSH.NET" Version="2024.0.0" />
<PackageReference Include="System.Net.FtpClient" Version="1.0.5824.34026" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net4')) AND '$(MSBuildRuntimeType)' == 'Core' AND '$(OS)' != 'Windows_NT'"> <ItemGroup Condition="$(TargetFramework.StartsWith('net4')) AND '$(MSBuildRuntimeType)' == 'Core' AND '$(OS)' != 'Windows_NT'">