Esempio n. 1
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);
            }