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
        }
 private string GetCompressionHeader(HgBundleCompression compression)
 {
     switch(compression)
     {
         case HgBundleCompression.None:
             return "HG10UN";
         case HgBundleCompression.BZip:
             //
             // Docs say that "HG10BZ" is the correct value, 
             // but BZip2OutputStream writes that "BZ" all by itself
             return "HG10";
         case HgBundleCompression.GZip:
             return "HG10GZ";
         default:
             throw new ArgumentOutOfRangeException("compression");
     } // switch
 }
 private Stream GetCompressedStream(Stream stream, HgBundleCompression compression)
 {
     switch(compression)
     {
         case HgBundleCompression.None:
             return new NonClosingStreamWrapper(stream);
         case HgBundleCompression.GZip:
             return new ZlibStream(stream, CompressionMode.Compress, CompressionLevel.BestCompression, true);
         case HgBundleCompression.BZip:
             return new BZip2OutputStream(stream, true);
         default:
             throw new ArgumentOutOfRangeException("compression");
     } // switch
 }