// Group: Individual File Management Functions // __________________________________________________________________________ /* Function: AddOrUpdateFile * * Adds a file or updates its last modification time. If the file was not previously known to the class, it will be treated as * new, whereas if it was known but has a different modification time it will be treated as changed. Returns whether this * call changed anything. It is okay to call this multiple times on the same file. * * This is assumed to be called for files that are in a file source so it automatically sets <File.InFileSource>. */ public bool AddOrUpdateFile(Path name, FileType type, DateTime lastModified, bool forceReparse = false) { lock (accessLock) { File file = files[name]; // If the file didn't exist in our records it's new if (file == null) { if (type == FileType.Image) { file = new ImageFile(name, lastModified); } else { file = new File(name, type, lastModified); } files.Add(file); filesAddedSinceStart.Add(file.ID); unprocessedChanges.AddNewFile(file); foreach (var changeWatcher in changeWatchers) { changeWatcher.OnAddFile(file); } return(true); } // Make sure the file isn't being re-added as a different type else if (file.Type != type) { throw new Exception("Added an existing file but the types didn't match."); } // If the file was previously marked as deleted it was recreated else if (file.Deleted) { file.Deleted = false; file.LastModified = lastModified; filesAddedSinceStart.Add(file.ID); unprocessedChanges.AddNewFile(file); foreach (var changeWatcher in changeWatchers) { changeWatcher.OnAddFile(file); } return(true); } // If the file changed or we're forcing everything to be reparsed anyway else if (file.LastModified != lastModified || forceReparse) { file.LastModified = lastModified; filesAddedSinceStart.Add(file.ID); unprocessedChanges.AddChangedFile(file); foreach (var changeWatcher in changeWatchers) { changeWatcher.OnFileChanged(file); } return(true); } // Otherwise the file is the same as the last time we saw it. else { // This is still important because it's needed to know which files do and don't exist since the last time // Natural Docs was run filesAddedSinceStart.Add(file.ID); return(false); } } }
/* Function: Load * Loads <Files.nd> and returns whether it was successful. If it wasn't it will still return valid objects, they will just * be empty. */ public bool Load(Path filename, out IDObjects.Manager <File> files) { files = new IDObjects.Manager <File>(Config.Manager.KeySettingsForPaths, false); BinaryFile binaryFile = new BinaryFile(); bool result = true; try { // We'll continue to handle 2.0 files in 2.0.2 since it's easy enough if (binaryFile.OpenForReading(filename, "2.0") == false) { result = false; } else { // [Int32: ID] // [String: Path] // [Byte: Type] // [Int64: Last Modification in Ticks or 0] // (if image) // [UInt32: Width in Pixels or 0 if unknown] // [UInt32: Height in Pixels or 0 if unknown] // ... // [Int32: 0] int id; Path path; FileType type; DateTime lastModification; File file; uint width, height; for (;;) { id = binaryFile.ReadInt32(); if (id == 0) { break; } path = binaryFile.ReadString(); type = (FileType)binaryFile.ReadByte(); lastModification = new DateTime(binaryFile.ReadInt64()); if (type == FileType.Image) { if (binaryFile.Version < "2.0.2") { width = 0; height = 0; } else { width = binaryFile.ReadUInt32(); height = binaryFile.ReadUInt32(); } if (width == 0 || height == 0) { // If this file is from a different version of Natural Docs, no matter which one, reset the last modification // time so they'll be reparsed and take another stab at getting the dimensions if (binaryFile.Version != Engine.Instance.Version) { lastModification = new DateTime(0); } file = new ImageFile(path, lastModification); } else { file = new ImageFile(path, lastModification, width, height); } } else { file = new File(path, type, lastModification); } file.ID = id; files.Add(file); } } } catch { result = false; } finally { binaryFile.Close(); } if (result == false) { files.Clear(); } return(result); }
// Group: Individual File Management Functions // __________________________________________________________________________ /* Function: AddOrUpdateFile * * Adds a file or updates its last modification time. If the file was not previously known to the class, it will be treated as * new, whereas if it was known but has a different modification time it will be treated as changed. Returns whether this * call changed anything. It is okay to call this multiple times on the same file. * * This is assumed to be called for files that are in a file source so it automatically sets <File.InFileSource>. */ public bool AddOrUpdateFile(Path name, FileType type, DateTime lastModified, bool forceReparse = false) { bool changed = false; Monitor.Enter(accessLock); try { File file = files[name]; // The file didn't exist in our records so it's new if (file == null) { if (type == FileType.Image) { file = new ImageFile(name, lastModified); } else { file = new File(name, type, lastModified); } file.Status = FileFlags.NewOrChanged; files.Add(file); foreach (var changeWatcher in changeWatchers) { changeWatcher.OnAddFile(file); } changed = true; } else if (file.Type != type) { throw new Exception("Added an existing file but the types didn't match."); } else if (file.Claimed == true) { if (file.LastModified != lastModified || file.StatusSinceClaimed == FileFlags.DeletedSinceClaimed || forceReparse) { bool wasDeletedSinceClaimed = (file.StatusSinceClaimed == FileFlags.DeletedSinceClaimed); file.LastModified = lastModified; file.StatusSinceClaimed = FileFlags.NewOrChangedSinceClaimed; foreach (var changeWatcher in changeWatchers) { if (wasDeletedSinceClaimed) { changeWatcher.OnAddFile(file); } else { changeWatcher.OnFileChanged(file); } } changed = true; } } else if (file.LastModified != lastModified || file.Status == FileFlags.Deleted || forceReparse) { bool wasDeleted = (file.Status == FileFlags.Deleted); file.LastModified = lastModified; file.Status = FileFlags.NewOrChanged; foreach (var changeWatcher in changeWatchers) { if (wasDeleted) { changeWatcher.OnAddFile(file); } else { changeWatcher.OnFileChanged(file); } } changed = true; } file.InFileSource = true; } finally { Monitor.Exit(accessLock); } return(changed); }