/// <summary> /// Deletes the file that is referred to by the specified path. /// </summary> /// <param name="path"></param> public static void Delete(string path) { if (string.IsNullOrWhiteSpace(path)) { return; } PathOp.CheckInvalidPathChars(path); DualityApp.SystemBackend.FileSystem.DeleteFile(path); }
/// <summary> /// Returns whether the specified path refers to an existing file. /// </summary> /// <param name="path"></param> /// <returns></returns> public static bool Exists(string path) { if (string.IsNullOrWhiteSpace(path)) { return(false); } PathOp.CheckInvalidPathChars(path); return(DualityApp.SystemBackend.FileSystem.FileExists(path)); }
/// <summary> /// Opens an existing file at the specified path and returns a <see cref="System.IO.Stream"/> to it. /// </summary> /// <param name="path"></param> /// <param name="mode"></param> public static Stream Open(string path, FileAccessMode mode) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentException("The specified path is null or whitespace-only."); } PathOp.CheckInvalidPathChars(path); return(DualityApp.SystemBackend.FileSystem.OpenFile(path, mode)); }
/// <summary> /// Creates a directory tree matching the specified directory path. /// </summary> /// <param name="path"></param> public static void Create(string path) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentException("The specified path is null or whitespace-only."); } PathOp.CheckInvalidPathChars(path); DualityApp.SystemBackend.FileSystem.CreateDirectory(path); }
/// <summary> /// Enumerates all directories that are located within the specified path. /// </summary> /// <param name="path"></param> /// <param name="recursive">If true, the specified path will be searched recursively and yield all descendant directory paths.</param> /// <returns></returns> public static IEnumerable <string> GetDirectories(string path, bool recursive = false) { if (string.IsNullOrWhiteSpace(path)) { return(Enumerable.Empty <string>()); } PathOp.CheckInvalidPathChars(path); return(DualityApp.SystemBackend.FileSystem.GetDirectories(path, recursive)); }
/// <summary> /// Deletes the directory that is referred to by the specified path. /// </summary> /// <param name="path"></param> public static void Delete(string path) { if (string.IsNullOrWhiteSpace(path)) { return; } PathOp.CheckInvalidPathChars(path); PathOp.ResolveFileSystem(ref path).DeleteDirectory(path); }
/// <summary> /// Returns whether the specified path refers to an existing directory. /// </summary> /// <param name="path"></param> /// <returns></returns> public static bool Exists(string path) { if (string.IsNullOrWhiteSpace(path)) { return(false); } PathOp.CheckInvalidPathChars(path); return(PathOp.ResolveFileSystem(ref path).DirectoryExists(path)); }
/// <summary> /// Creates or overwrites a file at the specified path and returns a <see cref="System.IO.Stream"/> to it. /// The returned stream has implicit read / write access. /// </summary> /// <param name="path"></param> public static Stream Create(string path) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentException("The specified path is null or whitespace-only."); } PathOp.CheckInvalidPathChars(path); return(PathOp.ResolveFileSystem(ref path).CreateFile(path)); }
public int GetHashCode(string obj) { if (string.IsNullOrWhiteSpace(obj)) { return(0); } else { return(PathOp.GetFullPath(obj).GetHashCode()); } }
/// <summary> /// Enumerates all directories that are located within the specified path. /// </summary> /// <param name="path"></param> /// <param name="recursive">If true, the specified path will be searched recursively and yield all descendant directory paths.</param> /// <returns></returns> public static IEnumerable <string> GetDirectories(string path, bool recursive = false) { if (string.IsNullOrWhiteSpace(path)) { return(Enumerable.Empty <string>()); } PathOp.CheckInvalidPathChars(path); int index = PathOp.IndexOfFileSystem(path); if (index == -1) { return(DualityApp.SystemBackend.FileSystem.GetDirectories(path, recursive)); } else { return(PathOp.PrepareFileSystemForEnumerationUnsafe(index, true, path, recursive)); } }
public bool Equals(string x, string y) { return(PathOp.ArePathsEqual(x, y)); }
/// <summary> /// Performs an aggregate operation on all new events, starting at the specified index. /// Each event will include all previous events in its aggregate check. /// </summary> /// <param name="addedStartingIndex"></param> private void AggregateNewlyAdded(int addedStartingIndex) { // Iterate backwards over newly added events, and run an aggregation step // with all previous events for each of them. for (int currentIndex = this.items.Count - 1; currentIndex >= addedStartingIndex; currentIndex--) { FileEvent current = this.items[currentIndex]; string currentOldFileName = PathOp.GetFileName(current.OldPath); string currentFileName = PathOp.GetFileName(current.Path); bool discardedCurrent = false; // Aggregate with previous events, so the latest event // in an aggregate chain is the one that defines event order. for (int prevIndex = currentIndex - 1; prevIndex >= 0; prevIndex--) { FileEvent prev = this.items[prevIndex]; string prevFileName = PathOp.GetFileName(prev.Path); bool consumedPrev = false; // Aggregate identical events if (current.Equals(prev)) { consumedPrev = true; } // Aggregate "delete Foo/A, create Bar/A" to "rename Foo/A to Bar/A" events. // Aggregate "delete Foo/A, create Foo/A" to "change Foo/A" events. else if ( current.Type == FileEventType.Created && prev.Type == FileEventType.Deleted && currentFileName == prevFileName) { current.Type = (current.Path == prev.Path) ? FileEventType.Changed : FileEventType.Renamed; current.OldPath = prev.Path; consumedPrev = true; } // Aggregate sequential renames / moves of the same file else if ( current.Type == FileEventType.Renamed && prev.Type == FileEventType.Renamed && currentOldFileName == prevFileName) { current.OldPath = prev.OldPath; consumedPrev = true; } // Aggregate "delete A, then rename B to A" into "delete B, changed A" events. // Some applications (like Photoshop) do stuff like that when saving files. else if ( current.Type == FileEventType.Renamed && prev.Type == FileEventType.Deleted && current.Path == prev.Path) { FileEvent deleted = current; deleted.Type = FileEventType.Deleted; deleted.Path = current.OldPath; deleted.OldPath = current.OldPath; this.items.Insert(currentIndex, deleted); currentIndex++; current.Type = FileEventType.Changed; current.OldPath = current.Path; consumedPrev = true; } // Aggregate anything before a delete into just the delete else if ( current.Type == FileEventType.Deleted && prev.Path == current.Path) { // Special case for previous renames: Translate the delete back to the old path if (prev.Type == FileEventType.Renamed) { current.Path = prev.OldPath; current.OldPath = prev.OldPath; } // Special case for previous creates: Discard both the delete and the create. else if (prev.Type == FileEventType.Created) { discardedCurrent = true; } consumedPrev = true; } // Aggregate anything after a create into just the create else if ( prev.Type == FileEventType.Created && (prev.Path == current.Path || prev.Path == current.OldPath)) { current.Type = FileEventType.Created; current.OldPath = current.Path; consumedPrev = true; } // Remove the previous item if it was aggregated with the current if (consumedPrev) { this.items.RemoveAt(prevIndex); // Update other indices to account for removed item currentIndex--; if (addedStartingIndex > prevIndex) { addedStartingIndex--; } } } // Filter out no-op events if (current.Type == FileEventType.Renamed && current.OldPath == current.Path) { discardedCurrent = true; } // Discard or update the current event if (discardedCurrent) { this.items.RemoveAt(currentIndex); } else { this.items[currentIndex] = current; } } }