public HgCommitStats Commit(HgBundle hgBundle)
        {
            log.Info("committing bundle");

            using(AcquireLock())
            {
                var hgJournal = new HgJournal(Store);
                var hgTransaction = new HgTransaction(Store, hgJournal);

                var tip = Changelog.Tip;

                try
                {
                    //
                    // Adding changesets
                    log.Info("committing changesets");
                    hgTransaction.Enlist(Changelog);
                    
                    int changesets;
                    var revisions = CommitChangelog(tip, hgBundle.Changelog, Changelog.Revlog, out changesets);

                    //
                    // Adding manifests
                    log.Info("committing manifests");
                    hgTransaction.Enlist(Manifest);

                    var manifests = 0;
                    Commit(revisions, hgBundle.Manifest, Manifest.Revlog, ref manifests);

                    //
                    // Adding file changes
                    log.Info("committing files");
                    var changedFiles = 0;
                    var changes = 0;

                    foreach(var file in hgBundle.Files)
                    {
                        changedFiles++;

                        log.Debug("committing '{0}'", file.Path.FullPath);

                        var filelog = Store.GetFilelog(file.Path) ?? Store.CreateFilelog(file.Path);
                        hgTransaction.Enlist(filelog);

                        var hgBundleGroup = file.File;

                        Commit(revisions, hgBundleGroup, filelog.Revlog, ref changes);
                    } // foreach

                    if(BundleCommitting != null)
                    {
                        var args = new HgBundleCommittedEventArgs(revisions.Keys.Select(k => Changelog[k]));
                        BundleCommitting(args);
                    } // if
                    
                    hgTransaction.Commit();

                    //
                    // We need to force changelog re-read since after CommitChangelog() the changelog is
                    // being read off a temp file.
                    changelog = null;

                    branchManager.RefreshBranchmap(tip == null ? 0 : tip.Metadata.Revision, Changelog.Tip.Metadata);

                    if(BundleCommitted != null)
                    {
                        var args = new HgBundleCommittedEventArgs(revisions.Keys.Select(k => Changelog[k]));
                        BundleCommitted(args);
                    } // if

                    return new HgCommitStats(changesets, manifests, changes, changedFiles);
                } // try
                catch(Exception e)
                {
                    log.ErrorException("could not commit bundle", e);

                    hgTransaction.Rollback();

                    //
                    // Reset changelog and manifest so that they'll be reread
                    changelog = null;
                    manifest = null;

                    throw;
                } // catch
            } // using
        }
        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
        }