public void WriteBundle(HgBundle hgBundle, Stream stream, HgBundleFormat format, HgBundleCompression compression) { // // First things first -- we need to write out bundle header var header = format == HgBundleFormat.BundlePre10 ? null : GetCompressionHeader(compression); if(header != null) { var headerBuffer = Encoding.ASCII.GetBytes(header); stream.Write(headerBuffer, 0, headerBuffer.Length); } // if using(var compressedStream = GetCompressedStream(stream, compression)) using(var binaryWriter = new BigEndianBinaryWriter(new BufferedStream(compressedStream, 1024 * 128))) { log.Debug("writing changesets"); WriteBundleGroup(hgBundle.Changelog, binaryWriter); binaryWriter.Flush(); log.Debug("writing manifests"); WriteBundleGroup(hgBundle.Manifest, binaryWriter); binaryWriter.Flush(); // // Sometimes HgBundleFile.File has no chunks and Mercurial chokes on that. log.Debug("writing files"); foreach(var file in hgBundle.Files) { string filePath = null; foreach(var chunk in file.File) { if(filePath == null) { filePath = file.Path.FullPath.TrimStart('/'); binaryWriter.Write((uint)filePath.Length + 4); binaryWriter.Write(hgEncoder.EncodeAsLocal(filePath)); log.Debug("writing file '{0}'", filePath); } // if WriteChunk(binaryWriter, chunk); } // foreach if(filePath != null) WriteZeroChunk(binaryWriter); binaryWriter.Flush(); } // foreach binaryWriter.Write((uint)0); binaryWriter.Flush(); compressedStream.Flush(); stream.Flush(); } // using }
public static byte[] Diff(byte[] source, byte[] destination) { var ms = new MemoryStream(); var bw = new BigEndianBinaryWriter(ms); if(source == null || source.Length == 0) { bw.Write((uint)0); bw.Write((uint)0); bw.Write((uint)destination.Length); bw.Write(destination); bw.Flush(); return ms.ToArray(); } // if var a = source.Split((byte)'\n'); var b = destination.Split((byte)'\n'); var p = new List<int> { 0 }; Array.ForEach(a, s => p.Add(p[p.Count - 1] + s.Length)); var d = new SequenceMatcher<Segment>(a, b, (l, r) => l.Equals(r)).GetMatchingBlocks(); int la = 0, lb = 0; foreach(var x in d) { int am = x.SourceIndex, bm = x.DestinationIndex, size = x.Length; var sz = (lb == bm && lb == 0) ? 0 : Enumerable.Range(lb, bm - lb).Select(i => b[i]).Sum(w => w.Length); if(am > la || sz > 0) { bw.Write((uint)p[la]); bw.Write((uint)p[am]); bw.Write((uint)sz); if(sz > 0) { for(var z = lb; z < bm; ++z) bw.Write(destination, b[z].Offset, b[z].Length); } // if } // if la = am + size; lb = bm + size; } // foreach bw.Flush(); return ms.ToArray(); }