public HgDiffFile(HgRepository repo, HgManifestEntry manifest, string path)
 {
   this.Path = path;
   this.Revision = -1;
   _repo = repo;
   _manifest = manifest;
 }
        public override HgManifestEntry this[uint revision]
        {
            get
            {
                var largefilesEnabledManifestEntry = underlyingManifest[revision];
                var manifestEntry = new HgManifestEntry(
                    largefilesEnabledManifestEntry.Metadata, 
                    largefilesEnabledManifestEntry.Files.Select(f => new HgManifestFileEntry(new HgPath(f.Path.FullPath.SubstringAfter(".hglf/")), f.FilelogNodeID)).ToList());

                return manifestEntry;
            }
        }
        public byte[] WriteManifestEntry(HgManifestEntry hgManifestEntry)
        {
            using(var memoryStream = new MemoryStream(1024 * 1024))
            {
                foreach(var hgManifestFileEntry in hgManifestEntry.Files.OrderBy(mfe => mfe.Path.FullPath))
                {
                    var buffer = hgEncoder.EncodeAsLocal(hgManifestFileEntry.Path.FullPath.TrimStart('/'));
                    memoryStream.Write(buffer, 0, buffer.Length);
                    memoryStream.WriteByte(0);

                    buffer = hgEncoder.EncodeAsLocal(hgManifestFileEntry.FilelogNodeID.Long);
                    memoryStream.Write(buffer, 0, buffer.Length);
                    memoryStream.WriteByte((byte)'\n');
                } // foreach

                return memoryStream.ToArray();
            } // using
        }
        public HgManifestTree GetManifestTreeNode(HgRepository hgRepository, HgManifestEntry hgManifestEntry, HgPath hgPath)
        {
            var separators = hgPath.FullPath.Count(c => c == '/');
            
            var paths =
                hgManifestEntry.Files.
                    Select(f => new {
                        file = f,
                        separators = f.Path.FullPath.Count(c => c == '/')
                    }).
                    Where(f => f.file.Path.FullPath.StartsWith(hgPath.FullPath)).
                    ToList();

            var directories =
                paths.
                    Where(d => d.separators > separators).
                    Select(d => d.file.Path.FullPath.SubstringBeforeNth("/", separators)).
                    Distinct().
                    Select(d => HgManifestNode.Directory(new HgPath(d))).
                    ToList();
            
            var files = 
                paths.
                    Where(f => f.separators == separators).
                    Select(f => HgManifestNode.File(f.file.Path, f.file.FilelogNodeID)).
                    ToList();

            var subrepositories =
                hgRepository.GetSubrepositories(hgManifestEntry).
                    Select(s => new {
                        subrepository = s,
                        separators = s.Path.FullPath.Count(c => c == '/')
                    }).
                    Where(s => s.subrepository.Path.FullPath.StartsWith(hgPath.FullPath) && s.separators == separators).
                    Select(s => HgManifestNode.Subrepository(s.subrepository.Path, s.subrepository.NodeID)).
                    ToList();

            return new HgManifestTree(hgPath, directories.Append(files).Append(subrepositories));
        }
        public IEnumerable<HgSubrepository> ReadSubrepositories(HgManifestEntry hgManifestEntry)
        {
            var hgsub = hgManifestEntry[".hgsub"];
            var hgsubstate = hgManifestEntry[".hgsubstate"];

            if(hgsub == null || hgsubstate == null) yield break;

            var hgsubText = hgRepository.Encoder.DecodeAsUtf8(hgRepository.GetFile(hgsub).Data);
            var hgsubstateText = hgRepository.Encoder.DecodeAsUtf8(hgRepository.GetFile(hgsubstate).Data);

            var subrepositories = 
                hgsubText.
                    Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).
                    Select(s => s.Split('=')).
                    Where(s => s.Length == 2).
                    Select(s => new {
                        path = new HgPath(s[0].Trim()),
                        repositoryPath = s[1].Trim()
                    }).
                    ToDictionary(s => s.path, s => s.repositoryPath);

            var subrepositoryStates = 
                hgsubstateText.
                    Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).
                    Select(s => new {
                        nodeID = new HgNodeID(s.SubstringBefore(" ").Trim()),
                        path = new HgPath(s.SubstringAfter(" ").Trim())
                    }).
                    ToDictionary(s => s.path, s => s.nodeID);

            foreach(var subrepository in subrepositories)
            {
                if(!subrepositoryStates.ContainsKey(subrepository.Key))
                    yield return new HgSubrepository(subrepository.Key, subrepository.Value, HgNodeID.Null);
                else
                    yield return new HgSubrepository(subrepository.Key, subrepository.Value, subrepositoryStates[subrepository.Key]);
            } // foreach
        }
        public HgNodeID Commit(HgCommit hgCommit)
        {
            var hgJournal = new HgJournal(Store);
            var hgTransaction = new HgTransaction(Store, hgJournal);

            var tip = Changelog.Tip;

            try
            {
                var manifestFileEntries = new List<HgManifestFileEntry>();
                foreach(var file in hgCommit.Files)
                {
                    
                    var filelog = Store.GetFilelog(file.Path) ?? Store.CreateFilelog(file.Path);
                    hgTransaction.Enlist(filelog);

                    var fileNodeID = Commit(file.FirstParentNodeID, file.SecondParentNodeID, file.Content, filelog.Revlog);
                    manifestFileEntries.Add(new HgManifestFileEntry(file.Path, fileNodeID));
                } // foreach

                //
                // We need to alter existing manifest here
                var manifestEntry = new HgManifestEntry(null, manifestFileEntries);
                if(hgCommit.FirstParentNodeID != HgNodeID.Null)
                {
                    var firstParentChangeset = Changelog[hgCommit.FirstParentNodeID];
                    var firstParentManifest = Manifest[firstParentChangeset.ManifestNodeID];

                    var previousManifestFileEntries = firstParentManifest.Files.ToList();

                    while(manifestFileEntries.Count > 0)
                    {
                        var mfe = manifestFileEntries[0];
                        manifestFileEntries.Remove(mfe);

                        var i = previousManifestFileEntries.FindIndex(e => e.Path == mfe.Path);
                        if(i == -1)
                            previousManifestFileEntries.Add(mfe);
                        else
                            previousManifestFileEntries[i] = mfe;
                    } // while

                    manifestEntry = new HgManifestEntry(null, previousManifestFileEntries);
                } // if

                var manifestEntryData = new HgManifestWriter(Encoder).WriteManifestEntry(manifestEntry);

                var manifestFirstParentNodeID = Manifest.Revlog.Entries.Any() ? 
                    Manifest.Revlog.Entries[Manifest.Revlog.Entries.Count - 1].NodeID :
                    HgNodeID.Null;

                hgTransaction.Enlist(Manifest);
                var manifestNodeID = Commit(manifestFirstParentNodeID, HgNodeID.Null, manifestEntryData, Manifest.Revlog);

                var hgChangeset = new HgChangeset(null, manifestNodeID, hgCommit.CommittedBy, hgCommit.CommittedAt, hgCommit.Branch, HgNodeID.Null, hgCommit.Files.Select(f => f.Path.FullPath.TrimStart('/')), hgCommit.Comment);
                var changesetEntryData = new HgChangelogWriter().WriteChangeset(hgChangeset);

                hgTransaction.Enlist(Changelog);
                var changesetNodeID = Commit(hgCommit.FirstParentNodeID, hgCommit.SecondParentNodeID, changesetEntryData, Changelog.Revlog);

                hgTransaction.Commit();

                changelog = null;

                branchManager.RefreshBranchmap(tip == null ? 0 : tip.Metadata.Revision, Changelog.Tip.Metadata);
                
                return changesetNodeID;
            } // try
            catch(Exception)
            {
                hgTransaction.Rollback();
                throw;
            } // catch
        }
 public IList<HgSubrepository> GetSubrepositories(HgManifestEntry hgManifestEntry)
 {
     var reader = new HgSubrepositoryReader(this);
     return new List<HgSubrepository>(reader.ReadSubrepositories(hgManifestEntry));
 }