using InnovEnergy.SysTools.Edges; using InnovEnergy.SysTools.Utils; namespace InnovEnergy.SysTools.Remote; public static class RemoteFileIo { public static Boolean Exists(this RemotePath remotePath) { var (host, path) = remotePath; return "test" .Opt("e") .Arg(path) .At(host) .ExecuteBlocking() .ExitCode == 0; } // TODO: how to find out if ssh has failed or remote command? public static Boolean DirectoryExists(this RemotePath remotePath) { var (host, path) = remotePath; return "test" .Opt("d") .Arg(path) .At(host) .ExecuteBlocking() .ExitCode == 0; } public static Boolean FileExists(this RemotePath remotePath) { var (host, path) = remotePath; return "test" .Opt("f") .Arg(path) .At(host) .ExecuteBlocking() .ExitCode == 0; } public static Boolean DirectoryExists(this RemotePath remotePath, String directoryName) { return DirectoryExists(remotePath / directoryName); } public static Boolean FileExists(this RemotePath remotePath, String fileName) { return DirectoryExists(remotePath / fileName); } public static IEnumerable Directories(this RemotePath rp) { var (host, path) = rp; return "find" .Arg(path) .Opt1("mindepth", 1) .Opt1("maxdepth", 1) .Opt1("type", "d") .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut .Select(p => new RemotePath(host, p)); } public static IEnumerable Files(this RemotePath rp) { var (host, path) = rp; return "find" .Arg(path) .Opt1("mindepth", 1) .Opt1("maxdepth", 1) .Opt1("type", "f") .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut .Select(p => new RemotePath(host, p)); } public static RemotePath CreateDirectory(this RemotePath remotePath) { var (host, path) = remotePath; "mkdir".Arg(path) .At(host) .ExecuteBlocking() .ThrowOnError(); return remotePath; } public static RemotePath MoveFileTo(this RemotePath sourcePath, RemotePath targetPath) { throw new NotImplementedException(); } public static RemotePath MoveDirectory(this RemotePath sourcePath, RemotePath targetPath) { throw new NotImplementedException(); } public static RemotePath CreateDirectory(this RemotePath path, String dirName) { return CreateDirectory(path / dirName); } public static RemotePath DeleteFile(this RemotePath remotePath) { var (host, path) = remotePath; // TODO: test file "rm".Arg(path) .At(host) .ExecuteBlocking() .ThrowOnError(); return remotePath; } public static RemotePath DeleteFile(this RemotePath path, String fileName) { return DeleteFile(path / fileName); } public static RemotePath DeleteDirectory(this RemotePath remotePath) { var (host, path) = remotePath; // TODO: test dir "rm".Opt("r") .Arg(path) .At(host) .ExecuteBlocking() .ThrowOnError(); return remotePath; } public static RemotePath DeleteDirectory(this RemotePath path, String directoryName) { return DeleteDirectory(path / directoryName); } public static RemotePath CopyDirectoryTo(this RemotePath sourceDir, RemotePath targetDir) { throw new NotImplementedException(); } public static RemotePath CopyFileTo(this RemotePath srcFile, RemotePath targetFile) { throw new NotImplementedException(); } public static RemotePath CopyFileToDirectory(this RemotePath srcFile, RemotePath targetDir) { throw new NotImplementedException(); } public static IEnumerable DescendantDirectories(this RemotePath remotePath) { var (host, path) = remotePath; return "find" .Arg(path) .Opt1("type", "d") .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut .Select(d => new RemotePath(host, d)); } public static IEnumerable DescendantFiles(this RemotePath remotePath) { var (host, path) = remotePath; return "find" .Arg(path) .Opt1("type", "f") .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut .Select(d => new RemotePath(host, d)); } public static IEnumerable Descendants(this RemotePath remotePath) { var (host, path) = remotePath; return "find" .Arg(path) .Opt1("mindepth", 1) .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut .Select(l => new RemotePath(host, l)); } public static IEnumerable ReadBytes(this RemotePath path) { throw new NotImplementedException(); } public static IReadOnlyList ReadLines(this RemotePath remotePath) { var (host, path) = remotePath; return "cat" .Arg(path) .At(host) .ExecuteBlocking() .ThrowOnError() .StdOut; } // public static IEnumerable ReadLines(this RemotePath path, Encoding encoding) // { // throw new NotImplementedException(); // } //public static String ReadText(this RemotePath path) => path.ReadText(Encoding.UTF8); public static String ReadText(this RemotePath rp) { var lines = ReadLines(rp); if (lines.Count == 0) return ""; if (lines.Count == 1) return lines[0]; return lines.Aggregate((a, b) => a.NewLine() + b); } public static RemotePath WriteText(this RemotePath rp, String text) { throw new NotImplementedException(); } public static RemotePath AppendLines(this RemotePath filePath, params String[] lines) { return AppendLines(filePath, (IEnumerable) lines); } public static RemotePath AppendLines(this RemotePath rp, IEnumerable lines) { return WriteLines(rp, lines, append: true); } public static RemotePath WriteLines(this RemotePath filePath, params String[] lines) { return WriteLines(filePath, (IEnumerable) lines); } public static RemotePath WriteLines(this RemotePath rp, IEnumerable lines) { return WriteLines(rp, lines, append: false); } private static RemotePath WriteLines(this RemotePath rp, IEnumerable lines, Boolean append) { var (host, path) = rp; var proc = "cat" .Arg(append ? ">>" : ">") .Arg(path) .At(host).ToAsyncProcess(); foreach (var line in lines) proc.StandardIn.OnNext(line); proc.StandardIn.OnCompleted(); // TODO: OnCompleted or not? // TODO: error handling var exitCode = proc.WaitForExit(); return rp; } public static RemotePath AppendText(this RemotePath filePath, String text) { throw new NotImplementedException(); } }