/// <summary> /// Performs a diff on a file at two revisions. /// </summary> /// <param name="DepotFilename"></param> /// <param name="RevA"></param> /// <param name="RevB"></param> /// <returns>List of changes between revisions.</returns> public DiffChange[] Diff2(string DepotFilename, int RevA, int RevB, bool bQuiet = false) { if (!bQuiet) { CommandUtils.Log("Diff2({0}, {1}, {2})", DepotFilename, RevA, RevB); } var Changes = new List<DiffChange>(); var Diff2Result = P4(String.Format("diff2 {0}#{1} {0}#{2}", DepotFilename, RevA, RevB), AllowSpew: false); var Diff2Output = Diff2Result.Output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); // Skip the first line - it contains only the diff description for (int DiffLineIndex = 1; DiffLineIndex < Diff2Output.Length; ++DiffLineIndex) { var DiffLine = Diff2Output[DiffLineIndex]; if (!String.IsNullOrEmpty(DiffLine) && Char.IsNumber(DiffLine[0])) { var NewChange = new DiffChange(Diff2Output, DiffLineIndex); Changes.Add(NewChange); } } return Changes.ToArray(); }
/// <summary> /// Applies 'delete' to the blame file /// </summary> private static int ApplyDiffDelete(List<BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { Result.RemoveRange(ChangeInfo.SourceStart + DestOffset, ChangeInfo.SourceCount); DestOffset -= ChangeInfo.SourceCount; return DestOffset; }
/// <summary> /// Applies 'add' to the diff file. /// </summary> private static int ApplyDiffAdd(RevisionInfo RevisionInfo, List<BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { int DestInsert = ChangeInfo.DestStart; for (int ContentIndex = 0; ContentIndex < ChangeInfo.NewContents.Count; ++ContentIndex, ++DestInsert, ++DestOffset) { var AddBlame = new BlameLineInfo(ChangeInfo.NewContents[ContentIndex], RevisionInfo); Result.Insert(DestInsert, AddBlame); } return DestOffset; }
/// <summary> /// Applies a single Diff change to the Blame file. /// </summary> /// <param name="RevisionInfo"></param> /// <param name="Result"></param> /// <param name="ChangeInfo"></param> /// <param name="DestOffset"></param> /// <returns></returns> private static int ApplyDiff(RevisionInfo RevisionInfo, List<BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { switch (ChangeInfo.Type) { case DiffChangeType.Add: DestOffset = ApplyDiffAdd(RevisionInfo, Result, ChangeInfo, DestOffset); break; case DiffChangeType.Delete: DestOffset = ApplyDiffDelete(Result, ChangeInfo, DestOffset); break; case DiffChangeType.Change: DestOffset = ApplyDiffChange(RevisionInfo, Result, ChangeInfo, DestOffset); break; } return DestOffset; }
/// <summary> /// Applies 'change' to the blame file. /// </summary> private static int ApplyDiffChange(RevisionInfo RevisionInfo, List<BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { // Remember the first revision for lines that are about to change var PreviousRevisions = new BlameLineInfo[ChangeInfo.SourceCount]; for (int PrevIndex = 0; PrevIndex < ChangeInfo.SourceCount; ++PrevIndex) { PreviousRevisions[PrevIndex] = Result[PrevIndex + ChangeInfo.SourceStart + DestOffset]; } // Apply Change as Delete+Add operation DestOffset = ApplyDiffDelete(Result, ChangeInfo, DestOffset); DestOffset = ApplyDiffAdd(RevisionInfo, Result, ChangeInfo, DestOffset); // Keep previous revisions for (int PrevIndex = 0; PrevIndex < PreviousRevisions.Length && PrevIndex < ChangeInfo.NewContents.Count; ++PrevIndex) { Result[PrevIndex + ChangeInfo.DestStart].PreviousRevisions.Add(PreviousRevisions[PrevIndex]); } return DestOffset; }
/// <summary> /// Goes through all changes from Diff result and applies them to the blame file. /// </summary> /// <param name="Source"></param> /// <param name="Diff"></param> /// <param name="RevisionInfo"></param> private static void ParseDiff(List<BlameLineInfo> Source, DiffChange[] Diff, RevisionInfo RevisionInfo) { int DestOffset = 0; foreach (var Change in Diff) { DestOffset = ApplyDiff(RevisionInfo, Source, Change, DestOffset); } }
/// <summary> /// Applies 'add' to the diff file. /// </summary> private static int ApplyDiffAdd(RevisionInfo RevisionInfo, List <BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { int DestInsert = ChangeInfo.DestStart; for (int ContentIndex = 0; ContentIndex < ChangeInfo.NewContents.Count; ++ContentIndex, ++DestInsert, ++DestOffset) { var AddBlame = new BlameLineInfo(ChangeInfo.NewContents[ContentIndex], RevisionInfo); Result.Insert(DestInsert, AddBlame); } return(DestOffset); }
/// <summary> /// Applies 'delete' to the blame file /// </summary> private static int ApplyDiffDelete(List <BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { Result.RemoveRange(ChangeInfo.SourceStart + DestOffset, ChangeInfo.SourceCount); DestOffset -= ChangeInfo.SourceCount; return(DestOffset); }
/// <summary> /// Applies 'change' to the blame file. /// </summary> private static int ApplyDiffChange(RevisionInfo RevisionInfo, List <BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { // Remember the first revision for lines that are about to change var PreviousRevisions = new BlameLineInfo[ChangeInfo.SourceCount]; for (int PrevIndex = 0; PrevIndex < ChangeInfo.SourceCount; ++PrevIndex) { PreviousRevisions[PrevIndex] = Result[PrevIndex + ChangeInfo.SourceStart + DestOffset]; } // Apply Change as Delete+Add operation DestOffset = ApplyDiffDelete(Result, ChangeInfo, DestOffset); DestOffset = ApplyDiffAdd(RevisionInfo, Result, ChangeInfo, DestOffset); // Keep previous revisions for (int PrevIndex = 0; PrevIndex < PreviousRevisions.Length && PrevIndex < ChangeInfo.NewContents.Count; ++PrevIndex) { Result[PrevIndex + ChangeInfo.DestStart].PreviousRevisions.Add(PreviousRevisions[PrevIndex]); } return(DestOffset); }
/// <summary> /// Applies a single Diff change to the Blame file. /// </summary> /// <param name="RevisionInfo"></param> /// <param name="Result"></param> /// <param name="ChangeInfo"></param> /// <param name="DestOffset"></param> /// <returns></returns> private static int ApplyDiff(RevisionInfo RevisionInfo, List <BlameLineInfo> Result, DiffChange ChangeInfo, int DestOffset) { switch (ChangeInfo.Type) { case DiffChangeType.Add: DestOffset = ApplyDiffAdd(RevisionInfo, Result, ChangeInfo, DestOffset); break; case DiffChangeType.Delete: DestOffset = ApplyDiffDelete(Result, ChangeInfo, DestOffset); break; case DiffChangeType.Change: DestOffset = ApplyDiffChange(RevisionInfo, Result, ChangeInfo, DestOffset); break; } return(DestOffset); }