Пример #1
0
        public bool RefreshHigherChanges(ulong id)
        {
            // first remove changes from this id
            RemoveHigherChanges(RootFolder, id);

            bool save = false;

            OpStorage storage = Storages.GetStorage(id);

            if (storage == null)
                return save;

            // this is the first step in auto-integration
            // go through this id's storage file, and add any changes or updates to our own system
            string path = Storages.GetFilePath(storage);

            if (!File.Exists(path))
                return save;

            try
            {
                using (TaggedStream filex = new TaggedStream(path, Protocol))
                using (IVCryptoStream crypto = IVCryptoStream.Load(filex, storage.File.Header.FileKey))
                {
                    PacketStream stream = new PacketStream(crypto, Protocol, FileAccess.Read);

                    ulong currentUID = 0;
                    LocalFolder currentFolder = RootFolder;
                    LocalFile currentFile = null;
                    bool ignoreCurrent = false;
                    bool readingProject = false;

                    G2Header header = null;

                    while (stream.ReadPacket(ref header))
                    {
                        if (header.Name == StoragePacket.Root)
                        {
                            StorageRoot root = StorageRoot.Decode(header);

                            readingProject = (root.ProjectID == ProjectID);
                        }

                        if (readingProject)
                        {
                            if (header.Name == StoragePacket.Folder)
                            {
                                StorageFolder readFolder = StorageFolder.Decode(header);

                                // if new uid
                                if (currentUID != readFolder.UID)
                                {
                                    // if only 1 entry in changes for previous file, remove it, its probably a dupe of local
                                    // and integration needs more than one file to happen
                                    if (currentFolder.HigherChanges.ContainsKey(id) && currentFolder.HigherChanges[id].Count == 1)
                                        currentFolder.HigherChanges.Remove(id);

                                    // set new id
                                    currentUID = readFolder.UID;

                                    // check scope
                                    ignoreCurrent = false;
                                    if (readFolder.Scope.Count > 0 && !Core.Trust.IsInScope(readFolder.Scope, Core.UserID, ProjectID))
                                        ignoreCurrent = true;

                                    bool added = false;

                                    while (!added)
                                    {
                                        if (currentFolder.Info.UID == readFolder.ParentUID)
                                        {
                                            LocalFolder subFolder = null;
                                            if (currentFolder.Folders.SafeTryGetValue(currentUID, out subFolder))
                                                currentFolder = subFolder;

                                            else
                                            {
                                                // if ignoring, add folder so we can traverse id's file, but dont save changes to local storage mapping
                                                if (ignoreCurrent)
                                                {
                                                    currentFolder = new LocalFolder(currentFolder, readFolder);
                                                    break;
                                                }

                                                // check for conflicting name
                                                currentFolder.Folders.LockReading(delegate()
                                                {
                                                    foreach (LocalFolder subfolder in currentFolder.Folders.Values)
                                                        if (!subfolder.Info.IsFlagged(StorageFlags.Archived) && subfolder.Info.Name == readFolder.Name)
                                                            subfolder.Info.Name = subfolder.Info.Name + ".fix";
                                                });

                                                // if not found, create folder
                                                currentFolder = currentFolder.AddFolderInfo(readFolder);
                                                save = true;
                                            }

                                            added = true;
                                        }

                                        else if (currentFolder.Parent == null)
                                            break; // error, couldn't find parent of folder that was read

                                        else if (currentFolder.Parent.GetType() == typeof(LocalFolder))
                                            currentFolder = currentFolder.Parent;

                                        else
                                            break;
                                    }
                                }

                                // if file does not equal null
                                if (currentFolder != null && !ignoreCurrent)
                                {
                                    // log change if file newer than ours
                                    // if if not in higher's history
                                    // or if file integrated by higher by a node we would have inherited from

                                    // we look for our own file in higher changes, if there then we can auto integrate

                                    if (readFolder.Date >= currentFolder.Info.Date)
                                        if (readFolder.IntegratedID == 0 ||
                                            readFolder.IntegratedID == Core.UserID ||
                                            Core.Trust.IsAdjacent(readFolder.IntegratedID, ProjectID))
                                            currentFolder.AddHigherChange(id, readFolder);
                                }

                            }

                            if (header.Name == StoragePacket.File)
                            {
                                StorageFile readFile = StorageFile.Decode(header);

                                // if new uid
                                if (currentUID != readFile.UID)
                                {
                                    // if only 1 entry in changes for previous file, remove it, its probably a dupe of local
                                    // and integration needs more than one file to happen
                                    if (currentFile != null && currentFile.HigherChanges.ContainsKey(id) && currentFile.HigherChanges[id].Count == 1)
                                        currentFile.HigherChanges.Remove(id);

                                    // set new id
                                    currentUID = readFile.UID;

                                    currentFile = null;

                                    // check scope
                                    ignoreCurrent = false;
                                    if (readFile.Scope.Count > 0 && !Core.Trust.IsInScope(readFile.Scope, Core.UserID, ProjectID))
                                    {
                                        ignoreCurrent = true;
                                        continue;
                                    }

                                    // if file exists with UID, else add file as temp, mark as changed
                                    if (!currentFolder.Files.SafeTryGetValue(currentUID, out currentFile))
                                    {
                                        // check for conflicting name
                                        currentFolder.Files.LockReading(delegate()
                                        {
                                            foreach (LocalFile checkFile in currentFolder.Files.Values)
                                                if (!checkFile.Info.IsFlagged(StorageFlags.Archived) && checkFile.Info.Name == readFile.Name)
                                                    checkFile.Info.Name = checkFile.Info.Name + ".fix";
                                        });

                                        currentFile = currentFolder.AddFileInfo(readFile);
                                        save = true;

                                        if (!Storages.FileExists(currentFile.Info))
                                            Storages.DownloadFile(id, currentFile.Info);
                                    }
                                }

                                // if file does not equal null
                                if (currentFile != null && !ignoreCurrent)
                                {
                                    if (readFile.Date >= currentFile.Info.Date)
                                        if (readFile.IntegratedID == 0 ||
                                            readFile.IntegratedID == Core.UserID ||
                                            Core.Trust.IsAdjacent(readFile.IntegratedID, ProjectID))
                                            currentFile.AddHigherChange(id, readFile);
                                }

                            }
                        }
                    }
                }
            }
            catch
            {

            }

            return save;
        }
Пример #2
0
        private FolderNode LoadWorking(TreeListNode parent, LocalFolder folder)
        {
            FolderNode node = new FolderNode(this, folder.Info, parent, false);
            node.Archived = folder.Archived;
            node.Integrated = folder.Integrated;

            if (SelectedFolder != null && node.Details.UID == SelectedFolder.Details.UID)
            {
                node.Selected = true;
                SelectedFolder = node;
            }

            if (!folder.Info.IsFlagged(StorageFlags.Archived) || GhostsButton.Checked)
                GuiUtils.InsertSubNode(parent, node);

            if (parent.GetType() == typeof(FolderNode))
            {
                FolderNode parentNode = (FolderNode)parent;
                parentNode.Folders[folder.Info.UID] = node;
            }

            if (node.Details.IsFlagged(StorageFlags.Modified))
                node.EnsureVisible();

            folder.Folders.LockReading(delegate()
            {
                foreach (LocalFolder sub in folder.Folders.Values)
                    LoadWorking(node, sub);
            });

            folder.Files.LockReading(delegate()
            {
                foreach (LocalFile file in folder.Files.Values)
                {
                    FileItem item = new FileItem(this, node, file.Info, false);
                    item.Archived = file.Archived;
                    item.Integrated = file.Integrated;

                    node.Files[file.Info.UID] = item;
                }
            });

            return node;
        }
Пример #3
0
        public void ReadyChange(LocalFolder folder)
        {
            Modified = true;
            PeriodicSave = true;

            folder.Modify(Core.TimeNow, folder.Info.Clone());
        }
Пример #4
0
        public void ReadyChange(LocalFolder folder, StorageFolder newInfo)
        {
            Modified = true;
            PeriodicSave = true;

            folder.Modify(Core.TimeNow, newInfo);
        }
Пример #5
0
        public void LockFolder(string dirpath, LocalFolder folder, bool subs, List<LockError> errors )
        {
            folder.Files.LockReading(delegate()
            {
                foreach (LocalFile file in folder.Files.Values)
                    Storages.LockFileCompletely(Core.UserID, ProjectID, dirpath, file.Archived, errors);
            });

            folder.Info.RemoveFlag(StorageFlags.Unlocked);

            if (subs)
                folder.Folders.LockReading(delegate()
                {
                    foreach (LocalFolder subfolder in folder.Folders.Values)
                        LockFolder(dirpath + Path.DirectorySeparatorChar + subfolder.Info.Name, subfolder, subs, errors);
                });

            try
            {
                string path = RootPath + dirpath;

                if (Directory.Exists(path) &&
                    Directory.GetDirectories(path).Length == 0 &&
                    Directory.GetFiles(path).Length == 0)
                    Directory.Delete(path, true);
            }
            catch { }

            Storages.CallFolderUpdate(ProjectID, Utilities.StripOneLevel(dirpath), folder.Info.UID, WorkingChange.Updated);
        }
Пример #6
0
        public void MoveFolder(LocalFolder sourceFolder, string destPath, List<string> errors)
        {
            // cant move root folder ;)
            if (sourceFolder.Parent == null)
                return;

            LocalFolder parentFolder = sourceFolder.Parent;

            LocalFolder destFolder = GetLocalFolder(destPath);

            if (destFolder == null || destFolder == parentFolder)
                return;

            // prevent folder from being moved inside of itself
            LocalFolder oneUp = destFolder;
            while (oneUp != null)
            {
                if (oneUp == sourceFolder)
                    return;

                oneUp = oneUp.Parent;
            }

            // if name exists with diff uid, return error
            destFolder.Folders.LockReading(delegate()
            {
                foreach (LocalFolder check in destFolder.Folders.Values)
                    if (check.Info.UID != sourceFolder.Info.UID &&
                        String.Compare(check.Info.Name, sourceFolder.Info.Name, true) == 0)
                    {
                        errors.Add("Folder with same name exists at " + destPath);
                        return;
                    }
            });

            // if uid exists in destination, merge histories with diff hashes
            WorkingChange destChange = WorkingChange.Created;
            WorkingChange sourceChange = WorkingChange.Updated;

            if (destFolder.Folders.SafeContainsKey(sourceFolder.Info.UID))
            {
                destFolder.Folders.SafeAdd(sourceFolder.Info.UID, sourceFolder);
                destChange = WorkingChange.Updated;
            }
            else
                destFolder.AddFolder(sourceFolder);

            // make note file was moved at source in destination
            LocalFolder ghost = new LocalFolder(parentFolder, sourceFolder.Info.Clone());

            ReadyChange(sourceFolder);
            sourceFolder.Parent = destFolder;
            string parentPath = parentFolder.GetPath();
            sourceFolder.Info.Note = "Moved from " + (parentPath == "" ? Path.DirectorySeparatorChar.ToString() : parentPath);
            sourceFolder.Info.ParentUID = destFolder.Info.UID;

            parentFolder.Folders.SafeRemove(sourceFolder.Info.UID);

            // only leave a ghost if this file has a committed history
            if (sourceFolder.Archived.SafeCount > 1 || !sourceFolder.Info.IsFlagged(StorageFlags.Modified))
            {
                ghost.Archived.SafeAddFirst(ghost.Info);
                parentFolder.AddFolder(ghost);
                ReadyChange(ghost); // created ghost needs to have 2 entries because applydiff() looks for date of previous file to apply change
                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
            string name = sourceFolder.Info.Name;
            if (File.Exists(RootPath + parentFolder.GetPath() + Path.DirectorySeparatorChar + name))
            {
                Directory.CreateDirectory(RootPath + destPath);

                // exceptions handled by caller
                File.Move(RootPath + parentFolder.GetPath() + Path.DirectorySeparatorChar + name,
                            RootPath + destPath + Path.DirectorySeparatorChar + name);
            }

            // file created at destination, updated at source
            Storages.CallFolderUpdate(ProjectID, destPath, sourceFolder.Info.UID, destChange);
            Storages.CallFolderUpdate(ProjectID, parentFolder.GetPath(), sourceFolder.Info.UID, sourceChange);
        }
Пример #7
0
        public LocalFolder AddFolderInfo(StorageFolder info)
        {
            LocalFolder folder = null;

            if (!Folders.SafeTryGetValue(info.UID, out folder))
            {
                folder = new LocalFolder(this, info);
                Folders.SafeAdd(info.UID, folder);
            }

            // if this is integration info, add to integration map
            if (info.IntegratedID != 0)
                folder.Integrated.SafeAdd(info.IntegratedID, info);

            // if history info, add to files history
            else
                folder.Archived.SafeAddLast(info);

            return folder;
        }
Пример #8
0
        public WorkingStorage(StorageService storages, uint project)
        {
            Storages = storages;
            Core = Storages.Core;
            Protocol = storages.Protocol;

            RootPath = Storages.GetRootPath(Core.UserID, project);
            ProjectID = project;

            StorageFolder packet = new StorageFolder();
            packet.Name = Core.Trust.GetProjectName(project) + " Files";

            RootFolder = new LocalFolder(null, packet);

            LoadWorking();
        }
Пример #9
0
        public void AddFolder(LocalFolder folder)
        {
            ulong uid = folder.Info.UID;

            Debug.Assert(!Folders.SafeContainsKey(uid));

            Folders.SafeAdd(uid, folder);
        }
Пример #10
0
        private void RemoveHigherChanges(LocalFolder folder, ulong id)
        {
            folder.Files.LockReading(delegate()
            {
                foreach (LocalFile file in folder.Files.Values)
                {
                    if (id == 0)
                        file.HigherChanges.Clear();

                    else if (file.HigherChanges.ContainsKey(id))
                        file.HigherChanges.Remove(id);
                }
            });

            folder.Folders.LockReading(delegate()
            {
                foreach (LocalFolder subfolder in folder.Folders.Values)
                {
                    if (id == 0)
                        subfolder.HigherChanges.Clear();

                    else if (subfolder.HigherChanges.ContainsKey(id))
                        subfolder.HigherChanges.Remove(id);

                    RemoveHigherChanges(subfolder, id);
                }
            });
        }
Пример #11
0
        private LocalFolder CreateNewFolder(LocalFolder parent, string dirname )
        {
            StorageFolder info = new StorageFolder();
            LocalFolder folder = new LocalFolder(parent, info);

            info.UID = Utilities.StrongRandUInt64(Core.StrongRndGen);
            info.ParentUID = parent.Info.UID;
            info.Name = dirname;
            info.Date = Core.TimeNow.ToUniversalTime();
            info.Revs = 5;

            folder.Archived.SafeAddFirst(info);

            return folder;
        }
Пример #12
0
        private bool AutoIntegrate(LocalFolder folder, List<LockError> errors)
        {
            bool save = false;

            if (!folder.Info.IsFlagged(StorageFlags.Modified))
            {
                StorageFolder latestFolder = folder.Info;

                // this will 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 (folder.HigherChanges.ContainsKey(id))
                        // higherChanges consists of files that are newer than local
                        foreach (StorageFolder changeFolder in folder.HigherChanges[id])
                            if (changeFolder.Date >= latestFolder.Date && Storages.ItemDiff(latestFolder, changeFolder) == StorageActions.None)
                            {
                                latestFolder = (StorageFolder)folder.HigherChanges[id][0]; // first element is newest file
                                break;
                            }

                // if current file/folder is not our own (itemdiff)
                if (Storages.ItemDiff(latestFolder, folder.Info) != StorageActions.None)
                {
                    ReplaceFolder(folder.GetPath(), latestFolder, false);

                    save = true;
                }
            }

            string dir = folder.GetPath();

            folder.Files.LockReading(delegate()
            {
                foreach (LocalFile file in folder.Files.Values)
                    if (AutoIntegrate(file, dir, errors))
                        save = true;
            });

            folder.Folders.LockReading(delegate()
            {
                foreach (LocalFolder subfolder in folder.Folders.Values)
                    if (AutoIntegrate(subfolder, errors))
                        save = true;
            });

            return save;
        }
Пример #13
0
        public LocalFolder(LocalFolder parent, StorageFolder info)
        {
            Parent = parent;

            Info = info;
        }
Пример #14
0
        public void WriteWorkingFile(CryptoStream stream, LocalFolder folder, bool commit)
        {
            // write files and all archives if tracked
            folder.Files.LockReading(delegate()
            {
                foreach (LocalFile file in folder.Files.Values)
                {
                    // history
                    int count = 0;
                    file.Archived.LockReading(delegate()
                    {
                        foreach (StorageFile archive in file.Archived)
                        {
                            if (file.Info.HashID == 0 || file.Info.Hash == null)
                                continue; // happens if file is still being hashed and auto-save is called

                            if (commit)
                            {
                                archive.RemoveFlag(StorageFlags.Modified);

                                if (count == file.Info.Revs)
                                    break;
                            }

                            Protocol.WriteToFile(archive, stream);
                            count++;
                        }
                    });

                    // integrated
                    file.Integrated.LockReading(delegate()
                    {
                        foreach (ulong who in file.Integrated.Keys)
                        {
                            StorageFile integrated = (StorageFile)file.Integrated[who];

                            if (commit)
                                integrated.RemoveFlag(StorageFlags.Modified);

                            integrated.IntegratedID = who;
                            Protocol.WriteToFile(integrated, stream);
                        }
                    });
                }
            });

            // foreach tracked folder, recurse
            folder.Folders.LockReading(delegate()
            {
                foreach (LocalFolder sub in folder.Folders.Values)
                {
                    // history
                    int count = 0;
                    sub.Archived.LockReading(delegate()
                    {
                        foreach (StorageFolder archive in sub.Archived)
                        {
                            if (commit)
                            {
                                archive.RemoveFlag(StorageFlags.Modified);

                                if (count == sub.Info.Revs)
                                    break;
                            }

                            Protocol.WriteToFile(archive, stream);
                            count++;
                        }
                    });

                    // integrated
                    sub.Integrated.LockReading(delegate()
                    {
                        foreach (StorageFile change in sub.Integrated.Values)
                        {
                            if (commit)
                                change.RemoveFlag(StorageFlags.Modified);

                            Protocol.WriteToFile(change, stream);
                        }
                    });

                    WriteWorkingFile(stream, sub, commit);
                }
            });
        }
Пример #15
0
        public void TrackFolder(string path, StorageFolder track)
        {
            string parentPath = Utilities.StripOneLevel(path);

            LocalFolder folder = GetLocalFolder(path);

            if (folder != null)
                return;

            LocalFolder parent = GetLocalFolder(parentPath);

            if (parent == null)
                return;

            folder = new LocalFolder(parent, track);
            folder.Archived.SafeAddFirst(track);
            folder.Info.SetFlag(StorageFlags.Modified);

            parent.AddFolder(folder);

            if (Directory.Exists(RootPath + parentPath + Path.DirectorySeparatorChar + folder.Info.Name))
                folder.Info.SetFlag(StorageFlags.Unlocked);

            Modified = true;
            PeriodicSave = true;

            Storages.CallFolderUpdate(ProjectID, parentPath, folder.Info.UID, WorkingChange.Created);
        }