using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; namespace Rokojori { public class FilesSync { public static void CopyTo( string fromPath, string toPath, bool overwrite = true ) { string? destinationDirectory = Path.GetDirectoryName( toPath ); if ( ! string.IsNullOrEmpty( destinationDirectory ) && ! Directory.Exists( destinationDirectory ) ) { Directory.CreateDirectory( destinationDirectory ); } File.Copy( fromPath, toPath, overwrite ); } public static void Move( string fromPath, string toPath ) { string? destinationDirectory = Path.GetDirectoryName( toPath ); if ( ! string.IsNullOrEmpty( destinationDirectory ) && ! Directory.Exists( destinationDirectory ) ) { Directory.CreateDirectory(destinationDirectory); } File.Move( fromPath, toPath ); } public static void DeleteExcept( string rootPath, List selectedPaths ) { if ( string.IsNullOrWhiteSpace( rootPath ) || ! Directory.Exists( rootPath ) ) { RJLog.Error( "Invalid root path:", rootPath ); return; } var normalizedSelectedPaths = selectedPaths .Select(p => Path.GetFullPath( p.TrimEnd( Path.DirectorySeparatorChar ) ) ) .ToList(); string normalizedRoot = Path.GetFullPath( rootPath ); ProcessDirectory( normalizedRoot, normalizedSelectedPaths ); } static void ProcessDirectory(string currentDir, List selectedPaths) { if ( IsSelectedOrInsideSelected( currentDir, selectedPaths ) ) { return; } foreach ( var file in Directory.GetFiles( currentDir ) ) { if ( ! IsSelectedOrInsideSelected( file, selectedPaths ) ) { File.SetAttributes( file, FileAttributes.Normal ); File.Delete( file ); } } foreach ( var dir in Directory.GetDirectories( currentDir ) ) { if ( IsSelectedOrInsideSelected(dir, selectedPaths ) ) { continue; } ProcessDirectory(dir, selectedPaths); if ( Directory.Exists( dir ) && ! Directory.EnumerateFileSystemEntries( dir ).Any() ) { Directory.Delete(dir); } } } static bool IsSelectedOrInsideSelected(string path, List selectedPaths) { string normalizedPath = Path.GetFullPath( path.TrimEnd( Path.DirectorySeparatorChar ) ); return selectedPaths.Any( selected => normalizedPath.Equals( selected, StringComparison.OrdinalIgnoreCase ) || normalizedPath.StartsWith( selected + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase ) ); } public static void Delete( string path ) { if ( string.IsNullOrWhiteSpace( path ) ) { return; } if ( File.Exists( path ) ) { File.Delete( path ); return; } if ( ! Directory.Exists( path ) ) { return; } Directory.Delete( path, recursive: true ); } public static bool DirectoryExists( string path ) { return Directory.Exists( path ); } public static bool FileExists( string path ) { return File.Exists( path ); } public static void CreateDirectory( string path ) { Directory.CreateDirectory( path ); } public static void EnsureParentDirectoryExists( string path ) { EnsureDirectoryExists( RegexUtility.ParentPath( path ) ); } public static void EnsureDirectoryExists( string path ) { if ( DirectoryExists( path ) ) { return; } CreateDirectory( path ); } public static List GetDirectories( string path, System.Func evaluator = null ) { var list = new List(); var files = Directory.GetDirectories( path, "*", SearchOption.TopDirectoryOnly ); var absolutePath = FilePath.Absolute( path ); for ( int i = 0; i < files.Length; i++ ) { var fileName = Path.GetFileName( files[ i ] ); var relativePath = absolutePath.MakeRelative( fileName ); if ( evaluator == null || evaluator( relativePath ) ) { list.Add( relativePath ); } } return list; } public static List GetFilesRecursive( string path, System.Func evaluator = null ) { return GetFiles( path, evaluator, true ); } public static List GetFiles( string path, System.Func evaluator = null, bool recursive = false ) { if ( ! Directory.Exists( path ) ) { return []; } var list = new List(); var files = Directory.GetFiles( path, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly ); var absoluteFilePath = FilePath.Absolute( path ); for ( int i = 0; i < files.Length; i++ ) { var relativePath = absoluteFilePath.MakeAbsolutePathRelative( files[ i ] ); if ( evaluator == null || evaluator( relativePath ) ) { list.Add( relativePath ); } } return list; } public static bool SaveUTF8( string path, string data ) { try { using ( StreamWriter streamWriter = File.CreateText( path ) ) { streamWriter.Write( data ); } } catch ( System.Exception e ) { RJLog.Log( "Could not save text: ", path, "exception", e ); return false; } return true; } public static bool SaveJSON( string path, object obj ) { return SaveUTF8( path, JSON.StringifyObject( obj ) ); } public static DateTimeOffset GetModificationTime( string path ) { return File.GetLastWriteTimeUtc( path ); } public static ISOTimeStamp GetModificationTimeStamp( string path ) { return ISOTimeStamp.FromDate( GetModificationTime( path ) ); } public static string LoadUTF8( string path ) { try { using ( StreamReader streamReader = File.OpenText( path ) ) { return streamReader.ReadToEnd(); } } catch ( System.Exception e ) { RJLog.Log( "Could not load text: ", path, "exception", e ); } return null; } public static T LoadJSON( string path ) where T:new() { if ( ! FilesSync.FileExists( path ) ) { return default(T); } var jsonString = LoadUTF8( path ); return JSON.ParseObject( jsonString ); } public static bool SaveBytes( string fileName, byte[] byteArray ) { try { using ( var fs = new FileStream( fileName, FileMode.Create, FileAccess.Write ) ) { fs.Write( byteArray, 0, byteArray.Length ); return true; } } catch ( System.Exception e ) { RJLog.Log( "Exception caught in process: {0}", e ); return false; } } } }