Пример #1
0
            public void AddDir(string name, string existingPath = null)
            {
                if (!TryGetEntry(name, out DirEntry de))
                {
                    var  tt = MakeNewDir(ref _context);
                    long lastWriteTime, lastAccessTime, creationTime;
                    if (existingPath == null)
                    {
                        lastWriteTime = lastAccessTime = creationTime = DateTime.Now.Ticks;
                    }
                    else
                    {
                        var fi = new FileInfo(existingPath);
                        lastWriteTime  = fi.LastWriteTimeUtc.Ticks;
                        lastAccessTime = fi.LastAccessTimeUtc.Ticks;
                        creationTime   = fi.CreationTimeUtc.Ticks;
                    }

                    // Add the new directory to the entry list
                    VersionEntry ve = new VersionEntry {
                        Uuid = tt.Item2, LastWriteTime = lastWriteTime, LastAccessTime = lastAccessTime, CreationTime = creationTime
                    };
                    DirEntry newDirEntry = new DirEntry {
                        Type = DirEntryType.Dir, Latest = 0
                    };
                    newDirEntry.Versions.Add(ve);
                    _data.Entries.Add(name, newDirEntry);

                    // Write the updated directory
                    Write();
                }
            }
Пример #2
0
            public static Dir Open(ref Context context, string path, bool create = false, bool filePathOk = false)
            {
                Dir dir = OpenRoot(ref context);

                string[] dirs = PathComponents(path);
                for (int ii = 0; ii < dirs.Length; ++ii)
                {
                    DirEntry de;
                    bool     exists = dir._data.Entries.TryGetValue(dirs[ii], out de);
                    if (exists)
                    {
                        if (IsFile(de))
                        {
                            if (ii == dirs.Length - 1 && filePathOk)
                            {
                                // The last component is a file, and this is allowed - success
                                return(dir);
                            }
                            else
                            {
                                throw new PathException("The destination path [" + path + "] has non-directory components in it.");
                            }
                        }

                        // Ascend into the next entry
                        dir._path += "/" + dirs[ii];
                        dir._fid   = new FileId(de.Versions[0].Uuid);
                        dir.Read();
                    }
                    else
                    {
                        if (create)
                        {
                            var tt = MakeNewDir(ref context);

                            // Add the new directory to the entry list
                            VersionEntry ve = new VersionEntry {
                                Uuid = tt.Item2, LastWriteTime = DateTime.Now.Ticks
                            };
                            DirEntry newDirEntry = new DirEntry {
                                Type = DirEntryType.Dir, Latest = 0
                            };
                            newDirEntry.Versions.Add(ve);
                            dir._data.Entries.Add(dirs[ii], newDirEntry);
                            dir.Write();

                            // Acend into the created directory
                            dir._path = LexicalPath.Combine(dir._path, dirs[ii]);
                            dir._fid  = new FileId(tt.Item2);
                            dir._data = tt.Item1._data;
                        }
                        else
                        {
                            throw new PathException("The destination path [" + path + "] doesn't exist.");
                        }
                    }
                }
                return(dir);
            }
Пример #3
0
 public static bool IsFile(DirEntry de)
 {
     return(de.Type == DirEntryType.File);
 }
Пример #4
0
 public static bool IsDir(DirEntry de)
 {
     return(de.Type == DirEntryType.Dir);
 }
Пример #5
0
            public bool PushFile(string src, string dest, bool force)
            {
                if (dest == null || dest.Length == 0)
                {
                    dest = Path.GetFileName(src);
                }

                DirEntry de;
                FileInfo fi     = new FileInfo(src);
                bool     exists = TryGetEntry(dest, out de);

                if (exists)
                {
                    bool changeDetected = force;
                    if (!changeDetected)
                    {
                        VersionEntry ve = de.Versions[de.Latest];
                        // Compare the file time
                        if (fi.LastWriteTimeUtc.Ticks > ve.LastWriteTime)
                        {
                            // Compare the size
                            if ((ulong)fi.Length != ve.Length)
                            {
                                changeDetected = true;
                            }
                            else if (_context.UseChecksums)
                            {
                                // Checksum check
                                byte[]            sha256 = new byte[32];
                                ComputeHashParams bb     = new ComputeHashParams {
                                };
                                bb.Hash = "sha256";
                                bb.Path = src;

                                using (MemoryStream ms = new MemoryStream())
                                {
                                    bb.WriteTo(ms);
                                    CodecDll.ComputeHash(ms.GetBuffer(), (uint)ms.Length, sha256, (uint)sha256.Length);
                                }

                                // Compare the hash
                                changeDetected = !sha256.SequenceEqual(ve.Checksum);
                            }

                            if (!changeDetected)
                            {
                                // Update the timestamp only
                                de.Versions[de.Latest].LastWriteTime = fi.LastWriteTimeUtc.Ticks;
                                return(true);
                            }
                        }
                    }

                    if (!changeDetected)
                    {
                        return(false);
                    }
                }
                else
                {
                    de = new DirEntry {
                        Type = DirEntryType.File, Latest = 0
                    };
                    AddEntry(dest, de);
                }

                VersionEntry versionToRemove = null;

                // Encode the file to a temp location
                using (var lp = new LocalPath(LocalUtils.GetTempFileName()))
                {
                    var hash = new byte[32];
                    CodecHelper.EncodeFile(ref _context, src, lp.Path, ref hash);

                    var newVersionEntry = new VersionEntry
                    {
                        Uuid           = Guid.NewGuid().ToString("N"),
                        LastWriteTime  = fi.LastWriteTimeUtc.Ticks,
                        LastAccessTime = fi.LastAccessTimeUtc.Ticks,
                        CreationTime   = fi.CreationTimeUtc.Ticks,
                        Attributes     = (int)fi.Attributes,
                        Length         = (ulong)fi.Length
                    };
                    newVersionEntry.Checksum = ByteString.CopyFrom(hash);

                    if (de.Versions.Count == 0)
                    {
                        // The very first version addition
                        de.Versions.Add(newVersionEntry);
                        Debug.Assert(de.Latest == 0);
                    }
                    else if (de.Versions.Count > 0 && de.Versions.Count >= _context.RepoCfg.MaxVersions)
                    {
                        de.Latest              = (de.Latest + 1) % _context.RepoCfg.MaxVersions;
                        versionToRemove        = de.Versions[de.Latest];
                        de.Versions[de.Latest] = newVersionEntry;
                    }
                    else
                    {
                        de.Versions.Add(newVersionEntry);
                        ++de.Latest;
                    }

                    // The in-memory directory is updated, perform the file operations
                    FileId fid = new FileId(newVersionEntry.Uuid);
                    _context.Storage.CreateDirectory(fid.DirectoryPath);
                    _context.Storage.Upload(lp.Path, fid.FullPath);
                }

                // Remove the previous version if necessary
                if (versionToRemove != null)
                {
                    _context.Storage.RemoveFile((new FileId(versionToRemove.Uuid)).FullPath);
                }

                Write();

                return(true);
            }
Пример #6
0
 public void AddEntry(string name, DirEntry de)
 {
     _data.Entries.Add(name, de);
 }
Пример #7
0
 public bool TryGetEntry(string entry, out DirEntry de)
 {
     return(_data.Entries.TryGetValue(entry, out de));
 }