public HgDiffDirectory(HgRepository repo, HgChangeset changeset)
    {
      _repo = repo;
      var manifest = repo.Manifest[changeset.ManifestNodeID];
      _files = manifest.Files
        .Select(f => new HgDiffFile(repo, manifest, f.Path.FullPath.TrimStart('/')))
        .ToDictionary(f => f.Path);

      var changes = new Queue<HgChangeset>();
      changes.Enqueue(changeset);
      HgDiffFile file;
      HgChangeset curr;

      while (changes.Any() && _files.Values.Any(f => f.Revision < 0))
      {
        curr = changes.Dequeue();
        foreach (var path in curr.Files)
        {
          if (_files.TryGetValue(path, out file) && file.Revision < 0)
            file.Revision = (int)curr.Metadata.Revision;
        }

        foreach (var change in curr.Metadata.Parents.Select(r => _repo.Changelog[r.NodeID]))
        {
          changes.Enqueue(change);
        }
      }
    }
 public HgCompareInfo(HgChangeset @base, HgChangeset head, IList<HgChangeset> changesets, IList<HgRollupFileDiffInfo> files)
 {
     Base = @base;
     Head = head;
     Changesets = new ReadOnlyCollection<HgChangeset>(changesets);
     Files = new ReadOnlyCollection<HgRollupFileDiffInfo>(files);
 }
        public byte[] WriteChangeset(HgChangeset hgChangeset)
        {
            var changeset = new StringBuilder();
            changeset.AppendFormat("{0}\n", hgChangeset.ManifestNodeID.Long);
            changeset.AppendFormat("{0} <{1}>\n", hgChangeset.CommittedBy.FullName, hgChangeset.CommittedBy.EmailAddress);
            changeset.AppendFormat("{0} {1}", (int)(hgChangeset.CommittedAt.ToUniversalTime() - Epoch).TotalSeconds, (int)-hgChangeset.CommittedAt.Offset.TotalSeconds);

            if(hgChangeset.Branch != HgBranch.Default)
            {
                changeset.AppendFormat(" branch:{0}", hgChangeset.Branch.Name);
                if(hgChangeset.Branch.Closed)
                    changeset.AppendFormat("\0close:1");
            } // if

            changeset.Append('\n');

            foreach(var file in hgChangeset.Files)
                changeset.AppendFormat("{0}\n", file.TrimStart('/'));

            changeset.Append('\n');
            changeset.Append(hgChangeset.Comment);

            var changesetData = Encoding.UTF8.GetBytes(changeset.ToString());
            return changesetData;
        }
    public HgMergeOperation(string repoPath, int local = -1, int remote = -1)
    {
      _repo = new HgRepository(repoPath);

      var heads = _repo.GetHeads().Select(h => _repo.Changelog[h.NodeID]).ToArray();
      _local = local < 0
        ? heads.FirstOrDefault(h => h.Branch.Name == "default") ?? heads.First()
        : _repo.Changelog[(uint)local];
      _remote = remote < 0
        ? heads.First(h => h.Metadata.NodeID != _local.Metadata.NodeID)
        : _repo.Changelog[(uint)remote];
      _baseRev = _repo.CommonParent(_local, _remote);

      var dict = new Dictionary<string, FileCompare>();

      foreach (var file in ChangesetManifestPaths(_repo, _baseRev))
      {
        dict[file] = new FileCompare() { Path = file, InBase = FileStatus.Unchanged };
      }

      FileCompare buffer;
      var modifiedFiles = new HashSet<string>(_local.Files);
      foreach (var file in ChangesetManifestPaths(_repo, _local))
      {
        if (!dict.TryGetValue(file, out buffer))
        {
          buffer = new FileCompare() { Path = file };
          dict.Add(file, buffer);
        }
        buffer.InLocal = modifiedFiles.Contains(file) ? FileStatus.Modified : FileStatus.Unchanged;
      }

      modifiedFiles = new HashSet<string>(_remote.Files);
      foreach (var file in ChangesetManifestPaths(_repo, _remote))
      {
        if (!dict.TryGetValue(file, out buffer))
        {
          buffer = new FileCompare() { Path = file };
          dict.Add(file, buffer);
        }
        buffer.InRemote = modifiedFiles.Contains(file) ? FileStatus.Modified : FileStatus.Unchanged;
      }

      _compares = dict.Values.ToArray();
    }
        private IDictionary<HgNodeID, uint> CommitChangelog(HgChangeset tip, IEnumerable<HgChunk> chunks, HgRevlog hgRevlog, out int changesets)
        {
            var revisions = new Dictionary<HgNodeID, uint>();
            var revision = tip == null ? 0 : 
                tip.Metadata.Revision + 1;
            
            changesets = 0;

            var hgRevlogWriter = new HgRevlogWriter(hgRevlog, atomicFileSystem);
            changesets = 
                hgRevlogWriter.WriteRevlogEntries(chunks, 
                    n => {
                        var linkRevision = revision++;
                        revisions[n] = linkRevision;

                        return linkRevision;
                    }, 
                    e => {
                        revisions[e.NodeID] = e.Revision;
                    });

            return revisions;
        }
        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 HgAnnotationLine(HgChangeset changeset, string line)
 {
     Changeset = changeset;
     Line = line;
 }
 public HgChangesetDetails(HgChangeset changeset, IEnumerable<HgChangesetFileDetails> files)
 {
     Changeset = changeset;
     Files = new ReadOnlyCollection<HgChangesetFileDetails>(new List<HgChangesetFileDetails>(files));
 }
 private static IEnumerable<string> ChangesetManifestPaths(HgRepository repo, HgChangeset ch)
 {
   return repo.Manifest[ch.ManifestNodeID].Files.Select(f => f.Path.FullPath.TrimStart('/'));
 }
 private byte[] GetFileBytes(HgChangeset change, string relPath)
 {
   var fileNode = _repo.Manifest[change.ManifestNodeID].GetFile(relPath);
   if (fileNode == null) return new byte[] { };
   return _repo.GetFile(fileNode).Data;
 }