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(); } }
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); }
public static bool IsFile(DirEntry de) { return(de.Type == DirEntryType.File); }
public static bool IsDir(DirEntry de) { return(de.Type == DirEntryType.Dir); }
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); }
public void AddEntry(string name, DirEntry de) { _data.Entries.Add(name, de); }
public bool TryGetEntry(string entry, out DirEntry de) { return(_data.Entries.TryGetValue(entry, out de)); }