Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.0 KiB

using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Text.Json.Serialization;
using StabilityMatrix.Core.Converters.Json;
namespace StabilityMatrix.Core.Models.FileInterfaces;
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[JsonConverter(typeof(StringJsonConverter<FilePath>))]
public partial class FilePath : FileSystemPath, IPathObject
{
private FileInfo? _info;
1 year ago
[JsonIgnore]
public FileInfo Info => _info ??= new FileInfo(FullPath);
[JsonIgnore]
public bool IsSymbolicLink
{
get
{
Info.Refresh();
return Info.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
}
1 year ago
[JsonIgnore]
public bool Exists => Info.Exists;
1 year ago
[JsonIgnore]
public string Name => Info.Name;
1 year ago
[JsonIgnore]
public string NameWithoutExtension => Path.GetFileNameWithoutExtension(Info.Name);
/// <inheritdoc cref="FileInfo.Extension"/>
[JsonIgnore]
public string Extension => Info.Extension;
/// <summary>
/// Get the directory of the file.
/// </summary>
[JsonIgnore]
public DirectoryPath? Directory
{
get
{
try
{
1 year ago
return Info.Directory == null ? null : new DirectoryPath(Info.Directory);
}
catch (DirectoryNotFoundException)
{
return null;
}
}
}
1 year ago
public FilePath(string path)
: base(path) { }
public FilePath(FileInfo fileInfo)
: base(fileInfo.FullName)
{
_info = fileInfo;
}
1 year ago
public FilePath(FileSystemPath path)
: base(path) { }
public FilePath(params string[] paths)
: base(paths) { }
public long GetSize()
{
Info.Refresh();
return Info.Length;
}
1 year ago
public long GetSize(bool includeSymbolicLinks)
{
1 year ago
if (!includeSymbolicLinks && IsSymbolicLink)
return 0;
return GetSize();
}
public Task<long> GetSizeAsync(bool includeSymbolicLinks)
{
return Task.Run(() => GetSize(includeSymbolicLinks));
}
1 year ago
/// <summary> Creates an empty file. </summary>
public void Create() => File.Create(FullPath).Close();
1 year ago
/// <summary> Deletes the file </summary>
public void Delete() => File.Delete(FullPath);
1 year ago
/// <summary> Deletes the file asynchronously </summary>
public Task DeleteAsync(CancellationToken ct = default)
{
return Task.Run(() => File.Delete(FullPath), ct);
}
// Methods specific to files
1 year ago
/// <summary> Read text </summary>
public string ReadAllText() => File.ReadAllText(FullPath);
1 year ago
/// <summary> Read text asynchronously </summary>
public Task<string> ReadAllTextAsync(CancellationToken ct = default)
{
return File.ReadAllTextAsync(FullPath, ct);
}
1 year ago
/// <summary> Write text </summary>
public void WriteAllText(string text) => File.WriteAllText(FullPath, text, Encoding.UTF8);
1 year ago
/// <summary> Write text asynchronously </summary>
public Task WriteAllTextAsync(string text, CancellationToken ct = default)
{
return File.WriteAllTextAsync(FullPath, text, Encoding.UTF8, ct);
}
1 year ago
/// <summary> Read bytes </summary>
public byte[] ReadAllBytes() => File.ReadAllBytes(FullPath);
1 year ago
/// <summary> Read bytes asynchronously </summary>
public Task<byte[]> ReadAllBytesAsync(CancellationToken ct = default)
{
return File.ReadAllBytesAsync(FullPath, ct);
}
1 year ago
/// <summary> Write bytes </summary>
public void WriteAllBytes(byte[] bytes) => File.WriteAllBytes(FullPath, bytes);
1 year ago
/// <summary> Write bytes asynchronously </summary>
public Task WriteAllBytesAsync(byte[] bytes, CancellationToken ct = default)
{
return File.WriteAllBytesAsync(FullPath, bytes, ct);
}
1 year ago
/// <summary>
/// Rename the file.
/// </summary>
public FilePath Rename(string fileName)
{
if (
Path.GetDirectoryName(FullPath) is { } directory
&& !string.IsNullOrWhiteSpace(directory)
)
{
var target = Path.Combine(directory, fileName);
Info.MoveTo(target, true);
return new FilePath(target);
}
throw new InvalidOperationException(
"Cannot rename a file path that is empty or has no directory"
);
}
/// <summary>
/// Move the file to a directory.
/// </summary>
public FilePath MoveTo(FilePath destinationFile)
{
Info.MoveTo(destinationFile.FullPath, true);
// Return the new path
return destinationFile;
}
1 year ago
/// <summary>
/// Move the file to a directory.
/// </summary>
public async Task<FilePath> MoveToDirectoryAsync(DirectoryPath directory)
{
await Task.Run(() => Info.MoveTo(directory.FullPath)).ConfigureAwait(false);
// Return the new path
return directory.JoinFile(this);
}
1 year ago
/// <summary>
/// Move the file to a target path.
/// </summary>
public async Task<FilePath> MoveToAsync(FilePath destinationFile)
{
await Task.Run(() => Info.MoveTo(destinationFile.FullPath)).ConfigureAwait(false);
// Return the new path
return destinationFile;
}
1 year ago
/// <summary>
/// Move the file to a target path with auto increment if the file already exists.
/// </summary>
/// <returns>The new path, possibly with incremented file name</returns>
public async Task<FilePath> MoveToWithIncrementAsync(
FilePath destinationFile,
int maxTries = 100
)
{
await Task.Yield();
var targetFile = destinationFile;
for (var i = 1; i < maxTries; i++)
{
if (!targetFile.Exists)
{
return await MoveToAsync(targetFile).ConfigureAwait(false);
}
targetFile = destinationFile.WithName(
destinationFile.NameWithoutExtension + $" ({i})" + destinationFile.Extension
);
}
throw new IOException(
$"Could not move file to {destinationFile} because it already exists."
);
}
/// <summary>
/// Copy the file to a target path.
/// </summary>
public FilePath CopyTo(FilePath destinationFile, bool overwrite = false)
{
Info.CopyTo(destinationFile.FullPath, overwrite);
// Return the new path
return destinationFile;
}
/// <summary>
/// Copy the file to a target path asynchronously.
/// </summary>
public async Task<FilePath> CopyToAsync(FilePath destinationFile, bool overwrite = false)
{
await using var sourceStream = Info.OpenRead();
await using var destinationStream = destinationFile.Info.OpenWrite();
await sourceStream.CopyToAsync(destinationStream).ConfigureAwait(false);
// Return the new path
return destinationFile;
}
// Implicit conversions to and from string
public static implicit operator string(FilePath path) => path.FullPath;
1 year ago
public static implicit operator FilePath(string path) => new(path);
}