/// <summary>Return the child nodes for 'node'</summary> private static IEnumerable <TreeNode> GetChildNodes(TreeNode node) { var path = new Path(node.FullPath); return(Path_.EnumFileSystem(path.Name, SearchOption.TopDirectoryOnly) .Where(fi => fi.IsDirectory()) .Select(fi => new TreeNode(fi.Name, node.TriState))); }
/// <summary>Does the work of finding and identifying duplicates</summary> private void FindDuplicates(ProgressForm dlg, object ctx, ProgressForm.Progress progress) // worker thread context { // Build a map of file data var dir = string.Empty; foreach (var path in Settings.SearchPaths) { if (dlg.CancelPending) { break; } foreach (var fi in Path_.EnumFileSystem(path, search_flags:SearchOption.AllDirectories, exclude:FileAttributes.Directory).Cast <System.IO.FileInfo>()) { if (dlg.CancelPending) { break; } // Report progress whenever the directory changes var d = Path_.Directory(fi.FullName) ?? string.Empty; if (d != dir) { dir = d; progress(new ProgressForm.UserState { Description = $"Scanning files...\r\n{dir}" }); } try { // Create file info for the file and look for a duplicate var finfo = new FileInfo(fi); FileInfo existing = FInfoMap.TryGetValue(finfo.Key, out existing) ? existing : null; if (existing != null) { Dispatcher.Invoke(() => { existing.Duplicates.Add(finfo); var idx = Duplicates.BinarySearch(existing, FileInfo.Compare); if (idx < 0) { Duplicates.Insert(~idx, existing); } }); } else { FInfoMap.Add(finfo.Key, finfo); } } catch (Exception ex) { Errors.Add($"Failed to add {fi.FullName} to the map. {ex.Message}"); } } } }
/// <summary></summary> private void InitJournalFiles() { // Parse all of the available journal files, in order var journal_files = Path_.EnumFileSystem(Settings.Instance.JournalFilesDir, SearchOption.TopDirectoryOnly, JournalRegex).OrderBy(x => x.Name); foreach (var file in journal_files) { JournalFilepath = file.FullName; JournalOffset = Parse(JournalFilepath, 0L); } }
public WatchedDir(string dirpath, ChangedHandler onchange, int id, object?ctx) { m_files = new Dictionary <string, WatchedFile>(); Path = dirpath; m_onchange = onchange; m_ctx = ctx; Id = id; // Get the files in the directory and create a watcher for each var files = Path_.EnumFileSystem(Path, SearchOption.TopDirectoryOnly, exclude: FileAttributes.Hidden | FileAttributes.Directory).ToList(); m_files = files.ToDictionary(x => x.FullName.ToLowerInvariant(), x => new WatchedFile(x.FullName, onchange, id, ctx)); }
/// <summary>Called after 'path' has been removed from the collection</summary> private void HandlePathRemoved(Path path) { // Remember, 'path' may not have been in the collection, but may be a child // of a path that is in the collection. var p = new StringBuilder(); var parts = path.Name.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); // Look for a path that is an ancestral parent of 'path' var part_idx = 0; for (; part_idx != parts.Length; ++part_idx) { p.Append(parts[part_idx]).Append("\\"); // If the parent path is in the collection, we need to replace // it with its children except for 'p.Append(parts[i+1])' var idx = Paths.BinarySearch(p.ToString(), Path.Compare); if (idx >= 0) { break; } } // If a parent is found, we need to add child paths for the ancestral siblings of 'path' if (part_idx != parts.Length) { // Remove the parent path var idx = Paths.BinarySearch(p.ToString(), Path.Compare); Paths.RemoveAt(idx); // Add the child paths for the ancestral siblings of 'path' for (++part_idx; part_idx != parts.Length; ++part_idx) { var siblings = Path_.EnumFileSystem(path.Text.Substring(0, p.Length), SearchOption.TopDirectoryOnly).Where(x => x.IsDirectory()); foreach (var sib in siblings) { if (string.CompareOrdinal(parts[part_idx], sib.Name.ToLowerInvariant()) == 0) { continue; } Paths.AddOrdered(sib.FullName, Path.Compare); } p.Append(parts[part_idx]).Append("\\"); } } // Update the check boxes UpdateTree(); }
/// <summary>Enumerate the types that implement the interface 'TInterface'</summary> public static IEnumerable <PluginFile> Enumerate(string directory, SearchOption search = SearchOption.TopDirectoryOnly, string regex_filter = DefaultRegexPattern) { // Build a list of assemblies to check var filedata = Path_.EnumFileSystem(directory, search, regex_filter, exclude: FileAttributes.Directory).ToList(); // Load each assembly and look for types that are flagged with the Plugin attribute foreach (var fd in filedata) { var ass = Assembly.LoadFile(fd.FullName); foreach (var plugin in Enumerate(ass)) { yield return(plugin); } } }
/// <summary>Notify observers about the changed items</summary> public bool NotifyChanged() { // Scan the directory and notify about created, deleted, or changed files var current_files = Path_.EnumFileSystem(Path, SearchOption.TopDirectoryOnly, exclude: FileAttributes.Hidden | FileAttributes.Directory) .Select(x => x.FullName).ToList(); var existing = current_files .ToHashSet(x => x.ToLowerInvariant()); foreach (var path in current_files) { // If there is an existing watcher for the file, simply check for changed if (m_files.TryGetValue(path.ToLowerInvariant(), out var file)) { // File unchanged if (!file.HasChanged) { continue; } // File changed, but change not handled if (!file.NotifyChanged()) { continue; } // File no longer exists, remove from 'm_files' if (!Path_.FileExists(file.Path)) { m_files.Remove(file.Path.ToLowerInvariant()); } continue; } // If this is a new file, notify then add file = new WatchedFile(path, m_onchange, Id, m_ctx); if (file.NotifyChanged()) { m_files[path.ToLowerInvariant()] = file; } } return(true); }
/// <summary>Build a map of the files in 'root'</summary> private Dictionary <string, FileSystemInfo> BuildMap(string root, string ignore_patn) { var dir = root.ToLowerInvariant(); var map = new Dictionary <string, FileSystemInfo>(); foreach (var finfo in Path_.EnumFileSystem(root, search_flags:SearchOption.AllDirectories)) { var d = (Path.GetDirectoryName(finfo.FullName) ?? string.Empty).ToLowerInvariant(); if (d != dir) { Console.WriteLine(d); dir = d; } // If the file matches the ignore pattern, skip it if (ignore_patn != null && Regex.IsMatch(finfo.FullName, ignore_patn, RegexOptions.IgnoreCase)) { continue; } try { var k = MakeKey(finfo); if (map.TryGetValue(k, out var existing)) { Console.WriteLine($"Existing duplicate found:\n {finfo.FullName}\n {existing.FullName}\n"); continue; } map.Add(k, finfo); } catch (Exception ex) { Console.WriteLine($"Failed to add {finfo.FullName} to the map"); Console.WriteLine($"Reason: {ex.Message}"); } } return(map); }
// Market data contains a set of 'Instruments' (currency pairs). // Each pair has a separate database containing tables of candles for // each time frame public MarketData(MainModel model) { Model = model; Instruments = new BindingSource <Instrument> { DataSource = new BindingListEx <Instrument>(), PerItemClear = true }; // Ensure the price data cache directory exists if (!Path_.DirExists(Model.Settings.General.PriceDataCacheDir)) { Directory.CreateDirectory(Model.Settings.General.PriceDataCacheDir); } // Add instruments for the price data we know about const string price_data_file_pattern = @"PriceData_(\w+)\.db"; foreach (var fd in Path_.EnumFileSystem(Model.Settings.General.PriceDataCacheDir, regex_filter:price_data_file_pattern)) { var sym = fd.FileName.SubstringRegex(price_data_file_pattern, RegexOptions.IgnoreCase)[0]; GetOrCreateInstrument(sym); } }
/// <summary>Called after 'path' has been added to the collection</summary> private void HandlePathAdded(Path path) { // Look for paths that would include 'path' already var p = new StringBuilder(); var parts = path.Name.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0, iend = parts.Length - 1; i < iend; ++i) { p.Append(parts[i]).Append("\\"); // If a parent path is in the collection already, we don't need 'path' var idx = Paths.BinarySearch(p.ToString(), Path.Compare); if (idx >= 0) { idx = Paths.BinarySearch(path, Path.Compare); if (idx >= 0) { Paths.RemoveAt(idx); } return; } } // Remove any paths that are children of 'path' { var idx = Paths.BinarySearch(path, Path.Compare); if (idx < 0) { idx = ~idx; } else { ++idx; } // Find the range of paths to remove var count = Paths.Skip(idx).Count(x => x.Name.StartsWith(path.Name)); Paths.RemoveRange(idx, count); } // Check the siblings of 'path', if all are in 'Paths' then we can remove // all of these child paths and replace it with the parent path p.Clear().Append(path.Name); for (int i = parts.Length; i-- != 0;) { p.Length -= parts[i].Length + 1; if (p.Length == 0 || !Path_.EnumFileSystem(p.ToString(), SearchOption.TopDirectoryOnly) .Where(x => Bit.AllSet(x.Attributes, FileAttributes.Directory)) .All(x => Paths.BinarySearch(x.FullName, Path.Compare) >= 0)) { break; // Not all child paths of 'p' are in 'Paths' } // Do this as we go, because the test above needs paths we add here using (Paths.SuspendEvents(true)) { var parent = new Path(path.Text.Substring(0, p.Length)); var idx = Paths.BinarySearch(parent, Path.Compare); if (idx < 0) { idx = ~idx; } else { throw new Exception($"Paths contains {parent} and {Paths[idx]}. {Paths[idx]} should not be in 'Paths' as it's covered by {parent}"); } // Remove all children of 'parent' var count = Paths.Skip(idx).Count(x => x.Name.StartsWith(parent.Name)); Paths.RemoveRange(idx, count); // Add 'parent' Paths.Insert(idx, parent); } } // Update the check boxes UpdateTree(); }
/// <summary> /// Smart copy from 'src' to 'dst'. Loosely like XCopy. /// 'src' can be a single file, a comma separated list of files, or a directory<para/> /// 'dst' can be a /// if 'src' is a directory, </summary> public static void Copy(string src, string dst, bool overwrite = false, bool only_if_modified = false, bool ignore_non_existing = false, Action <string>?feedback = null, bool show_unchanged = false) { var src_is_dir = Path_.IsDirectory(src); var dst_is_dir = Path_.IsDirectory(dst) || dst.EndsWith("/") || dst.EndsWith("\\") || src_is_dir; // Find the names of the source files to copy var files = new List <string>(); if (src_is_dir) { files = Path_.EnumFileSystem(src, SearchOption.AllDirectories).Select(x => x.FullName).ToList(); } else if (Path_.FileExists(src)) { files = new List <string>() { src } } ; else if (src.Contains('*') || src.Contains('?')) { files = Path_.EnumFileSystem(src, SearchOption.AllDirectories, new Pattern(EPattern.Wildcard, src).RegexString).Select(x => x.FullName).ToList(); } else if (!ignore_non_existing) { throw new FileNotFoundException($"'{src}' does not exist"); } // If the 'src' represents multiple files, 'dst' must be a directory if (src_is_dir || files.Count > 1) { // if 'dst' doesn't exist, assume it's a directory if (!Path_.DirExists(dst)) { dst_is_dir = true; } // or if it does exist, check that it is actually a directory else if (!dst_is_dir) { throw new FileNotFoundException($"'{dst}' is not a valid directory"); } } // Ensure that 'dstdir' exists. (Canonicalise fixes the case where 'dst' is a drive, e.g. 'C:\') var dstdir = Path_.Canonicalise((dst_is_dir ? dst : Path_.Directory(dst)).TrimEnd('/', '\\')); if (!Path_.DirExists(dstdir)) { Directory.CreateDirectory(dstdir); } // Copy the file(s) to 'dst' foreach (var srcfile in files) { // If 'dst' is a directory, use the same filename from 'srcfile' var dstfile = string.Empty; if (dst_is_dir) { var spath = src_is_dir ? Path_.RelativePath(src, srcfile) : Path_.FileName(srcfile); dstfile = Path_.CombinePath(dstdir, spath); } else { dstfile = dst; } // If 'srcfile' is a directory, ensure the directory exists at the destination if (Path_.IsDirectory(srcfile)) { if (!dst_is_dir) { throw new Exception($"ERROR: {dst} is not a directory"); } // Create the directory at the destination if (!Path_.DirExists(dstfile)) { System.IO.Directory.CreateDirectory(dstfile); } if (feedback != null) { feedback(srcfile + " --> " + dstfile); } } else { // Copy if modified or always based on the flag if (only_if_modified && !Path_.DiffContent(srcfile, dstfile)) { if (feedback != null && show_unchanged) { feedback(srcfile + " --> unchanged"); } continue; } // Ensure the directory path exists var d = Path_.Directory(dstfile); var f = Path_.FileName(dstfile); if (!Path_.DirExists(d)) { System.IO.Directory.CreateDirectory(d); } if (feedback != null) { feedback(srcfile + " --> " + dstfile); } File.Copy(srcfile, dstfile, overwrite); } } }
/// <summary>Search for the full path of adb.exe</summary> private void AutoDetectAdbPath() { // If the full path is saved in the settings, use that (if it's valid) if (Path_.FileExists(m_settings.AdbFullPath)) { SetAdbPath(m_settings.AdbFullPath); return; } // Quick check the most likely spot var likely_path = Path.Combine(Environment.GetEnvironmentVariable("ANDROID_HOME") ?? string.Empty, @"platform-tools\adb.exe"); if (Path_.FileExists(likely_path)) { SetAdbPath(likely_path); return; } // Not found? longer search... const string msg = "Searching for the Android Debugging Bridge application...\r\n" + "\r\n" + "Trying Path: {0}...\r\n" + "\r\n" + "Click cancel to locate it manually."; var adb_path = string.Empty; var search_paths = new[] { Environment.GetEnvironmentVariable("ANDROID_HOME"), Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Android\android-sdk\platform-tools", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Android\android-sdk\platform-tools", @"D:\Program Files (x86)\Android\android-sdk\platform-tools", @"D:\Program Files\Android\android-sdk\platform-tools", @"E:\Program Files (x86)\Android\android-sdk\platform-tools", @"E:\Program Files\Android\android-sdk\platform-tools", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"C:\" }; var res = DialogResult.Cancel; try { // Search for 'adb.exe' var find_adb = new ProgressForm("Locating 'adb.exe'...", string.Format(msg, string.Empty), Icon, ProgressBarStyle.Marquee, (s, a, cb) => { foreach (var path in search_paths) { if (s.CancelPending || adb_path.HasValue()) { break; } if (path == null || !Directory.Exists(path)) { continue; } cb(new ProgressForm.UserState { Description = string.Format(msg, path), ForceLayout = false }); Func <string, bool> progress = dir => { cb(ProgressForm.UserState.Empty); return(!s.CancelPending); }; foreach (var fi in Path_.EnumFileSystem(path, SearchOption.AllDirectories, regex_filter:@"adb\.exe", progress:progress)) { // Found one! adb_path = fi.FullName; return; } } }) { StartPosition = FormStartPosition.CenterParent, ClientSize = new Size(640, 280), }; using (find_adb) res = find_adb.ShowDialog(this); } catch (OperationCanceledException) {} catch (Exception ex) { Misc.ShowMessage(this, "An error occurred while searching for 'adb.exe'", "Locating 'adb.exe' failed", MessageBoxIcon.Error, ex); } if (res != DialogResult.OK) { return; } SetAdbPath(adb_path); }