예제 #1
0
        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);
            }
        }
예제 #2
0
            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;
                    }
                }
            }
예제 #3
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);
            }