/// <summary> /// Generates a Blame file for the specified depot file up to the specified revision (default = all revisions). Only the last revision is available for each line. /// </summary> /// <param name="DepotFilename"></param> /// <param name="MaxRevision"></param> /// <returns>An array of lines with blame information.</returns> public BlameLineInfo[] Blame(string DepotFilename) { CommandUtils.Log("Blame({0})", DepotFilename); // Get the file history. var FileHistory = Filelog(DepotFilename, bQuiet: true); // Construct the initial blame file from the first revision var AnnotateResult = Annotate(DepotFilename, bQuiet: true); var Blame = new List <BlameLineInfo>(AnnotateResult.Length); // Get the revision at each line and put it in the resulting Blame file for (int LineIndex = 0; LineIndex < AnnotateResult.Length; ++LineIndex) { var AnnotatedLine = AnnotateResult[LineIndex]; // The last line is empty, we could maybe just not iterate it but I'm not sure it's 100% of the time. if (!String.IsNullOrEmpty(AnnotatedLine)) { var RevisionEndIndex = AnnotatedLine.IndexOf(':'); var RevisionIndex = Int32.Parse(AnnotatedLine.Substring(0, RevisionEndIndex)) - 1; var LineContentsStart = RevisionEndIndex + 2; var LineContents = LineContentsStart >= AnnotatedLine.Length ? String.Empty : AnnotatedLine.Substring(LineContentsStart); var BlameInfo = new BlameLineInfo(LineContents, FileHistory[RevisionIndex]); Blame.Add(BlameInfo); } } return(Blame.ToArray()); }
/// <summary> /// Generates a Blame file for the specified depot file up to the specified revision (default = all revisions). Only the last revision is available for each line. /// </summary> /// <param name="DepotFilename"></param> /// <param name="MaxRevision"></param> /// <returns>An array of lines with blame information.</returns> public BlameLineInfo[] Blame(string DepotFilename) { CommandUtils.Log("Blame({0})", DepotFilename); // Get the file history. var FileHistory = Filelog(DepotFilename, bQuiet: true); // Construct the initial blame file from the first revision var AnnotateResult = Annotate(DepotFilename, bQuiet: true); var Blame = new List<BlameLineInfo>(AnnotateResult.Length); // Get the revision at each line and put it in the resulting Blame file for (int LineIndex = 0; LineIndex < AnnotateResult.Length; ++LineIndex) { var AnnotatedLine = AnnotateResult[LineIndex]; // The last line is empty, we could maybe just not iterate it but I'm not sure it's 100% of the time. if (!String.IsNullOrEmpty(AnnotatedLine)) { var RevisionEndIndex = AnnotatedLine.IndexOf(':'); var RevisionIndex = Int32.Parse(AnnotatedLine.Substring(0, RevisionEndIndex)) - 1; var LineContentsStart = RevisionEndIndex + 2; var LineContents = LineContentsStart >= AnnotatedLine.Length ? String.Empty : AnnotatedLine.Substring(LineContentsStart); var BlameInfo = new BlameLineInfo(LineContents, FileHistory[RevisionIndex]); Blame.Add(BlameInfo); } } return Blame.ToArray(); }
/// <summary> /// Converts Print command output to a blame file. /// </summary> /// <param name="Output">Print command output</param> /// <param name="RevisionInfo">Revision of the printed file.</param> /// <returns>List of lines in the blame file.</returns> private static List <BlameLineInfo> PrintToBlame(string[] Lines, RevisionInfo RevisionInfo) { var InitialBlame = new List <BlameLineInfo>(); for (int LineIndex = 0; LineIndex < Lines.Length; ++LineIndex) { var LineInfo = new BlameLineInfo(Lines[LineIndex], RevisionInfo); InitialBlame.Add(LineInfo); } return(InitialBlame); }
/// <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 '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> /// Converts Print command output to a blame file. /// </summary> /// <param name="Output">Print command output</param> /// <param name="RevisionInfo">Revision of the printed file.</param> /// <returns>List of lines in the blame file.</returns> private static List<BlameLineInfo> PrintToBlame(string[] Lines, RevisionInfo RevisionInfo) { var InitialBlame = new List<BlameLineInfo>(); for (int LineIndex = 0; LineIndex < Lines.Length; ++LineIndex) { var LineInfo = new BlameLineInfo(Lines[LineIndex], RevisionInfo); InitialBlame.Add(LineInfo); } return InitialBlame; }
/// <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 '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; }