public void CreateRoot(ref Context context) { context.Storage.CreateDirectory(ObjectsDir); BaseDir baseDir = new Core.BaseDir { Eyecatcher = EyeCatcher }; // Serialize to a temp file using (var path = new LocalPath(LocalUtils.GetTempFileName(suffix: ".dir"))) using (var encodedPath = new LocalPath(LocalUtils.GetTempFileName(suffix: ".edir"))) { FileStream output = File.OpenWrite(path.Path); // Write the directory to a file baseDir.WriteTo(output); output.Close(); byte[] hash = new byte[32]; CodecHelper.EncodeFile(ref context, path.Path, encodedPath.Path, ref hash); // Upload the file. It's removed by Upload. Upload(ref context, encodedPath.Path, RootId); } // Write the config using (var configPath = new LocalPath(LocalUtils.GetTempFileName(suffix: ".config"))) { context.RepoCfg.Save(configPath.Path); Upload(ref context, configPath.Path, RepoConfig.ConfigFile); } }
public void Write() { using (var rawContent = new LocalPath(LocalUtils.GetTempFileName(suffix: ".dir"))) { using (FileStream fs = File.OpenWrite(rawContent.Path)) { // Serialize the content _data.WriteTo(fs); } if (!File.Exists(rawContent.Path)) { throw new Exception($"The temporary file {rawContent.Path} disappeared!"); } // Use another temp file to encode the content using (var encodedPath = new LocalPath(LocalUtils.GetTempFileName(prefix: "cync", suffix: ".edir"))) { byte[] hash = new byte[32]; CodecHelper.EncodeFile(ref _context, rawContent.Path, encodedPath.Path, ref hash); // Make sure the target directory exists _context.Storage.CreateDirectory(_fid.DirectoryPath); // Upload the encoded file _context.Storage.Upload(encodedPath.Path, _fid.FullPath, true); _dirty = false; } } }
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); }