Пример #1
0
        private HgNodeID Commit(HgNodeID firstParentNodeID, HgNodeID secondParentNodeID, byte[] content, HgRevlog hgRevlog)
        {
            var data = new byte[]{};

            if(firstParentNodeID != HgNodeID.Null)
            {
                var hgRevlogReader = new HgRevlogReader(hgRevlog, fileSystem);
                data = hgRevlogReader.ReadRevlogEntry(firstParentNodeID).Data;
            } // if
                        
            var linkRevision = Changelog == null ? 0 : Changelog.Revlog.Entries.Count;

            var hgNodeID = new HgRevlogWriter(hgRevlog, fileSystem).WriteRevlogEntryData((uint)linkRevision, firstParentNodeID, secondParentNodeID, content);
            return hgNodeID;
        }
Пример #2
0
        private IEnumerable<HgChunk> BuildBundleGroup(HgRepository hgRepository, HgRevlog hgRevlog, HgRevset hgRevset, Action<HgRevlogEntryData> callback = null)
        {
            var hgRevlogReader = new HgRevlogReader(hgRevlog, fileSystem);
            
            //
            // See http://stackoverflow.com/a/10359273/60188. Pure magic
            var revisionChunks =
                hgRevset.
                    Select(hre => hre.Revision).
                    OrderBy(r => r).
                    Select((r, i) => new { r, i }).
                    GroupBy(x => x.r - x.i). 
                    Select(x => x.Select(xx => xx.r)).
                    Select(c => c.ToArray()).
                    ToArray();

            if(revisionChunks.Length == 0) yield break;

            byte[] prev = null;
            uint prevRev = uint.MaxValue;
            var prediff = false;
            var hgRevlogEntry = hgRevlog[revisionChunks[0][0]];
            if(hgRevlogEntry.FirstParentRevisionNodeID != HgNodeID.Null)
            {
                prev = hgRevlogReader.ReadRevlogEntry(hgRevlogEntry.FirstParentRevision).Data;
                prediff = true;
            }
            
            foreach(var revisionChunk in revisionChunks)
            {
                foreach(var revision in revisionChunk)
                {
                    hgRevlogEntry = hgRevlog[revision];
                    var hgChangeset = hgRepository.Changelog.Revlog[hgRevlogEntry.LinkRevision];
                
                    byte[] data = null;

                    if(prev == null || hgRevlogEntry.BaseRevision == hgRevlogEntry.Revision || prediff || (prevRev != UInt32.MaxValue && prevRev + 1 != revision))
                    {
                        var hgRevlogEntryData = hgRevlogReader.ReadRevlogEntry(revision);

                        if(prev == null)
                        {   
                            //
                            // Trivial case
                            var buffer = new byte[hgRevlogEntryData.Data.Length + 12];
                            using(var stream = new MemoryStream(buffer))
                            using(var binaryWriter = new BigEndianBinaryWriter(stream))
                            {
                                binaryWriter.Write((uint)0);
                                binaryWriter.Write((uint)0);
                                binaryWriter.Write((uint)hgRevlogEntryData.Data.Length);
                                binaryWriter.Write(hgRevlogEntryData.Data);
                            } // using

                            data = buffer;
                        } // if
                        else
                        {
                            data = BDiff.Diff(prev, hgRevlogEntryData.Data);
                            if(prediff)
                                prediff = false;
                        } // else

                        prev = hgRevlogEntryData.Data;
                    } // if
                    else
                    {
                        data = hgRevlogReader.ReadRevlogEntryDataRaw(revision);
                        prev = MPatch.Patch(prev, new List<byte[]> { data });
                    } // else

                    if(callback != null) callback(new HgRevlogEntryData(hgRevlogEntry, prev));

                    if(performIntegrityChecks)
                    {
                        var expectedNodeID = GetRevlogEntryDataNodeID(hgRevlogEntry.FirstParentRevisionNodeID, hgRevlogEntry.SecondParentRevisionNodeID, prev);
                        if(expectedNodeID != hgRevlogEntry.NodeID)
                        {
                            // TODO: Exception class
                            throw new ApplicationException("integrity violation for " + hgRevlogEntry.NodeID.Short);
                        } // if
                    } // if

                    var hgChunk = new HgChunk(hgRevlogEntry.NodeID, hgRevlogEntry.FirstParentRevisionNodeID, hgRevlogEntry.SecondParentRevisionNodeID,
                        hgChangeset.NodeID, data);

                    yield return hgChunk;

                    prevRev = revision;
                } // foreach
            } // foreach
        }