public HashPack(LocalFile file, string path, uint project, string dir) { File = file; Path = path; Project = project; Dir = dir; }
public void MergeFile(LocalFile file) { // if there are any unique files in the merge that don't exist locally, add them file.Archived.LockReading(delegate() { foreach (StorageFile merge in file.Archived) { // check if exists bool fileExists = false; Archived.LockReading(delegate() { foreach (StorageFile item in Archived) if (Utilities.MemCompare(item.InternalHash, merge.InternalHash)) { fileExists = true; break; } }); // add file if doesnt exist if (!fileExists) { bool added = false; LinkedListNode<StorageItem> item = null; Archived.LockReading(delegate() { for (item = Archived.First; item != null; item = item.Next) if (item.Value.Date > merge.Date) // loop until item is no longer the lowest (oldest) { added = true; break; } }); if (added && item != null) { if (item.Value == Info) Archived.SafeAddAfter(item, merge); // even if newest, the file being moved is the one at top else Archived.SafeAddBefore(item, merge); // put file in right spot } else Archived.SafeAddLast(merge); // oldest, at end } } }); }
public void ReadyChange(LocalFile file, StorageFile newInfo) { Modified = true; PeriodicSave = true; file.Modify(Core.TimeNow, newInfo); }
public void ReadyChange(LocalFile file) { Modified = true; PeriodicSave = true; file.Modify(Core.TimeNow, file.Info.Clone()); }
public void MoveFile(string sourcePath, string destPath, List<string> errors) { // get source folder string name = Path.GetFileName(sourcePath); sourcePath = Utilities.StripOneLevel(sourcePath); LocalFolder sourceFolder = GetLocalFolder(sourcePath); LocalFolder destFolder = GetLocalFolder(destPath); if (sourceFolder == null || destFolder == null || sourceFolder == destFolder) return; // get source file LocalFile sourceFile = sourceFolder.GetFile(name); if (sourceFile == null) return; // if name exists with diff uid, return error bool exists = false; destFolder.Files.LockReading(delegate() { foreach (LocalFile check in destFolder.Files.Values) if (check.Info.UID != sourceFile.Info.UID && String.Compare(check.Info.Name, sourceFile.Info.Name, true) == 0) { errors.Add("File with same name exists at " + destPath); exists = true; } }); if (exists) return; // if uid exists in destination, merge histories with diff hashes WorkingChange destChange = WorkingChange.Created; WorkingChange sourceChange = WorkingChange.Updated; LocalFile mergeFile = null; if (destFolder.Files.SafeTryGetValue(sourceFile.Info.UID, out mergeFile)) { sourceFile.MergeFile(mergeFile); destFolder.Files.SafeAdd(sourceFile.Info.UID, sourceFile); destChange = WorkingChange.Updated; } else destFolder.AddFile(sourceFile); // make note file was moved at source in destination LocalFile ghost = new LocalFile(sourceFile.Info.Clone()); // do before modified/new date set ReadyChange(sourceFile); sourceFile.Info.Note = "Moved from " + (sourcePath == "" ? Path.DirectorySeparatorChar.ToString() : sourcePath); sourceFolder.Files.SafeRemove(sourceFile.Info.UID); // only leave a ghost if this file has a committed history if (sourceFile.Archived.SafeCount > 1 || !sourceFile.Info.IsFlagged(StorageFlags.Modified)) { ghost.Archived.SafeAddFirst(ghost.Info); sourceFolder.AddFile(ghost); ReadyChange(ghost); ghost.Info.Note = "Moved to " + (destPath == "" ? Path.DirectorySeparatorChar.ToString() : destPath); ghost.Info.SetFlag(StorageFlags.Archived); } else sourceChange = WorkingChange.Removed; // move actual file if unlocked on disk, create new folder if need be if (File.Exists(RootPath + sourcePath + Path.DirectorySeparatorChar + name)) { Directory.CreateDirectory(RootPath + destPath); // exceptions handled by caller File.Move( RootPath + sourcePath + Path.DirectorySeparatorChar + name, RootPath + destPath + Path.DirectorySeparatorChar + name); } // file created at destination, updated at source Storages.CallFileUpdate(ProjectID, destPath, sourceFile.Info.UID, destChange); Storages.CallFileUpdate(ProjectID, sourcePath, sourceFile.Info.UID, sourceChange); }
void ReplaceFile(LocalFile file, StorageFile replacement, string dir, bool setModified, List<LockError> errors) { // this will lock file if it is unlocked bool unlocked = Storages.IsFileUnlocked(Core.UserID, ProjectID, dir, file.Info, false); Storages.LockFile(Core.UserID, ProjectID, dir, file.Info, false); if (setModified) ReadyChange(file, replacement); else { file.Info = replacement; file.Archived.SafeAddFirst(replacement); } if (unlocked) Storages.UnlockFile(Core.UserID, ProjectID, dir, file.Info, false, errors); }
public LocalFile AddFileInfo(StorageFile info) { LocalFile file = null; if (!Files.SafeTryGetValue(info.UID, out file)) { file = new LocalFile(info); Files.SafeAdd(info.UID, file); } if(info.IntegratedID != 0) file.Integrated.SafeAdd(info.IntegratedID, info); else file.Archived.SafeAddLast(info); return file; }
private LocalFile CreateNewFile(string name) { StorageFile info = new StorageFile(); LocalFile file = new LocalFile(info); info.UID = Utilities.StrongRandUInt64(Core.StrongRndGen); info.Name = name; info.Date = Core.TimeNow.ToUniversalTime(); info.Revs = 5; file.Archived.SafeAddFirst(info); return file; }
public void AddFile(LocalFile file) { ulong uid = file.Info.UID; Debug.Assert(!Files.SafeContainsKey(uid)); Files.SafeAdd(uid, file); }
private bool AutoIntegrate(LocalFile file, string dir, List<LockError> errors) { // If file/folder not flagged as modified if(file.Info.IsFlagged(StorageFlags.Modified)) return false; StorageFile latestFile = file.Info; List<StorageFile> inheritIntegrated = new List<StorageFile>(); ulong directHigher = (InheritIDs.Count >= 2) ? InheritIDs[1] : 0; // this process will find higher has integrated my file // and highest has integrated his file, and return latest // from self to highest foreach (ulong id in InheritIDs) if (file.HigherChanges.ContainsKey(id)) // higherChanges consists of files that are newer than local foreach (StorageFile changeFile in file.HigherChanges[id]) { if (changeFile.Date >= latestFile.Date && Storages.ItemDiff(latestFile, changeFile) == StorageActions.None) { latestFile = (StorageFile)file.HigherChanges[id][0]; // first element is newest file if (id != directHigher) break; } if (id == directHigher && changeFile.IntegratedID != 0 && Core.Trust.IsAdjacent(changeFile.IntegratedID, ProjectID)) inheritIntegrated.Add(changeFile); } // if current file/folder is not our own (itemdiff) bool save = false; if (Storages.ItemDiff(latestFile, file.Info) != StorageActions.None) { ReplaceFile(file, latestFile, dir , false, errors); save = true; } // merges integration list for nodes adjacent to ourselves // works even if higher integrates more files, but doesn't necessarily change the file's hash StorageItem prevIntegrated = null; foreach (StorageFile inherited in inheritIntegrated) { file.Integrated.SafeTryGetValue(inherited.IntegratedID, out prevIntegrated); if (prevIntegrated == null || inherited.Date > prevIntegrated.Date) { file.Integrated.SafeAdd(inherited.IntegratedID, inherited); save = true; } } return save; }
public void TrackFile(string path, StorageFile track) { LocalFolder folder = GetLocalFolder(path); if (folder == null) return; // increase references OpFile commonFile = null; if (Storages.FileMap.SafeTryGetValue(track.HashID, out commonFile)) commonFile.References++; LocalFile file = new LocalFile(track); file.Info.SetFlag(StorageFlags.Modified); file.Archived.SafeAddFirst(track); folder.AddFile(file); Modified = true; PeriodicSave = true; Storages.CallFileUpdate(ProjectID, folder.GetPath(), file.Info.UID, WorkingChange.Created); }
public void MarkforHash(LocalFile file, string path, uint project, string dir) { HashPack pack = new HashPack(file, path, project, dir); lock (HashFiles.Pending) if (HashFiles.Pending.Any(p => ((HashPack)p.Param2).File == file)) return; file.Info.Size = new FileInfo(path).Length; // set so we can get hash status HashFiles.Enqueue(() => HashFile(pack), pack); }