using CliWrap; using CliWrap.Buffered; namespace InnovEnergy.Lib.Utils; public class FileSystem { private static readonly String ProcName = Utils.ExecutingProcessName; private static readonly String TempPath = Path.GetTempPath(); private static Command Find { get; } = Cli.Wrap("find"); private static Command Stat { get; } = Cli.Wrap("stat"); private static Random Rng { get; } = new Random(); public static FileSystem Local { get; } = new FileSystem(); public static FileSystem OnHost(SshHost? host) => new FileSystem(host); private SshHost? Host { get; } private FileSystem(SshHost? host = null) { Host = host; } public Task> GetFiles(String path) { return GetFiles(path, FileType.RegularFile); } public Task> GetFilesRecursive(String path) { return GetFiles(path, FileType.RegularFile, maxDepth: Int16.MaxValue); } public Task> GetDirectories(String path) { return GetFiles(path, FileType.Directory); } public async Task> GetFiles(String path, FileType fileType, Int32 maxDepth = 1) { var result = await Find .WithArguments($"{path} -maxdepth {maxDepth} -type {(Char)fileType}") .OnHost(Host) .ExecuteBufferedAsync(); return result.StandardOutput.SplitLines(); } public Boolean FileExists(String path) { var stat = StatF(path); return stat.ExitCode == 0 && stat.StandardOutput.Trim() == "regular file"; } public Boolean DirectoryExists(String path) { var stat = StatF(path); return stat.ExitCode == 0 && stat.StandardOutput.Trim() == "directory"; } private BufferedCommandResult StatF(String path) { return Stat .WithArguments($"-c %F {path}") .OnHost(Host) .ExecuteBufferedAsync() .Task .Result; } [Obsolete] public static Disposable CreateTmpDir() { var path = GetRandomTempPath(); Directory.CreateDirectory(path); void Dispose() { try { Directory.Delete(path, recursive: true); } catch { // ignored } } return Disposable.Create(path, Dispose); } [Obsolete] private static String GetRandomTempPath() { lock (Rng) { return $"{TempPath}{ProcName}.{Rng.Next():x8}"; } } [Obsolete] public static Disposable CreateTempFile(String fileName) { var dir = CreateTmpDir(); var file = dir.Value.AppendPath(fileName); return Disposable.Create(file, dir.Dispose); } } public enum FileType : Byte { BlockDevice = (Byte) 'b', CharacterDevice = (Byte) 'c', Directory = (Byte) 'd', Pipe = (Byte) 'p', RegularFile = (Byte) 'f', SymbolicLink = (Byte) 'l', }