internal CmdStream Create() { // Start out by faking a merge of the whole main branch into itself var ms = new MergeSpan(Main, 0, Main.Info.CommandCount - 1, Main, 0); Link(ms); // Follow ancestors as well (up to the branch point) for (Branch b = Main; b != null; b = b.Parent) { Debug.Assert(b.Commands.Count > 0); if (b.Parent != null) { uint maxCmd = 0; // The ICreateBranch command may not be the last // command pushed to the results (it's possible that // a parent span has been injected prior to the branch // creation step). But if that does happen, confirm // that the last command we do have is immediately // after the branch point. Debug.Assert(Result.Count > 0); Cmd last = Result.Peek(); if (last.Data.Sequence == 0) { Debug.Assert(Object.ReferenceEquals(last.Branch, b)); Debug.Assert(last.Data.CmdName == nameof(ICreateBranch)); Debug.Assert(Object.ReferenceEquals(b.Commands[0], last.Data)); maxCmd = (last.Data as ICreateBranch).CommandCount - 1; } else { Debug.Assert(Object.ReferenceEquals(last.Branch, b.Parent)); Debug.Assert(b.Commands[0].CmdName == nameof(ICreateBranch)); Debug.Assert((b.Commands[0] as ICreateBranch).CommandCount == last.Data.Sequence); maxCmd = last.Data.Sequence - 1; } ms = new MergeSpan(b.Parent, 0, maxCmd, b, 0); Link(ms); } } // Confirm that all merge spans have been processed foreach (CmdData cd in GetAllData()) { MergeSpan[] spans = PopMergeSpans(cd).ToArray(); if (spans.Length > 0) { throw new ApplicationException("Not all merge spans were processed"); } } // Apply any updates Log.Info($"Loaded stream with {Result.Count} commands"); return(new CmdStream(Main, Result)); }
CmdData[] GetSourceData(MergeSpan ms) { Branch source = ms.Source; uint numCmd = ms.MaxCmd + 1; if (Data.TryGetValue(source, out CmdData[] data))