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
        }
Beispiel #2
0
        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();
        }