public GitBlame Blame(string filename, string from, string lines, Encoding encoding) { from = FixPath(from); filename = FixPath(filename); string blameCommand = string.Format("blame --porcelain -M -w -l{0} \"{1}\" -- \"{2}\"", lines != null ? " -L " + lines : "", from, filename); var itemsStrings = RunCacheableCmd( AppSettings.GitCommand, blameCommand, LosslessEncoding ) .Split('\n'); GitBlame blame = new GitBlame(); GitBlameHeader blameHeader = null; GitBlameLine blameLine = null; for (int i = 0; i < itemsStrings.GetLength(0); i++) { try { string line = itemsStrings[i]; //The contents of the actual line is output after the above header, prefixed by a TAB. This is to allow adding more header elements later. if (line.StartsWith("\t")) { blameLine.LineText = line.Substring(1) //trim ONLY first tab .Trim(new char[] { '\r' }); //trim \r, this is a workaround for a \r\n bug blameLine.LineText = ReEncodeStringFromLossless(blameLine.LineText, encoding); } else if (line.StartsWith("author-mail")) blameHeader.AuthorMail = ReEncodeStringFromLossless(line.Substring("author-mail".Length).Trim()); else if (line.StartsWith("author-time")) blameHeader.AuthorTime = DateTimeUtils.ParseUnixTime(line.Substring("author-time".Length).Trim()); else if (line.StartsWith("author-tz")) blameHeader.AuthorTimeZone = line.Substring("author-tz".Length).Trim(); else if (line.StartsWith("author")) { blameHeader = new GitBlameHeader(); blameHeader.CommitGuid = blameLine.CommitGuid; blameHeader.Author = ReEncodeStringFromLossless(line.Substring("author".Length).Trim()); blame.Headers.Add(blameHeader); } else if (line.StartsWith("committer-mail")) blameHeader.CommitterMail = line.Substring("committer-mail".Length).Trim(); else if (line.StartsWith("committer-time")) blameHeader.CommitterTime = DateTimeUtils.ParseUnixTime(line.Substring("committer-time".Length).Trim()); else if (line.StartsWith("committer-tz")) blameHeader.CommitterTimeZone = line.Substring("committer-tz".Length).Trim(); else if (line.StartsWith("committer")) blameHeader.Committer = ReEncodeStringFromLossless(line.Substring("committer".Length).Trim()); else if (line.StartsWith("summary")) blameHeader.Summary = ReEncodeStringFromLossless(line.Substring("summary".Length).Trim()); else if (line.StartsWith("filename")) blameHeader.FileName = ReEncodeFileNameFromLossless(line.Substring("filename".Length).Trim()); else if (line.IndexOf(' ') == 40) //SHA1, create new line! { blameLine = new GitBlameLine(); var headerParams = line.Split(' '); blameLine.CommitGuid = headerParams[0]; if (headerParams.Length >= 3) { blameLine.OriginLineNumber = int.Parse(headerParams[1]); blameLine.FinalLineNumber = int.Parse(headerParams[2]); } blame.Lines.Add(blameLine); } } catch { //Catch all parser errors, and ignore them all! //We should never get here... AppSettings.GitLog.Log("Error parsing output from command: " + blameCommand + "\n\nPlease report a bug!"); } } return blame; }
public static GitBlame Blame(string filename, string from) { from = FixPath(from); filename = FixPath(filename); string blameCommand = string.Format("blame --porcelain -M -w -l \"{0}\" -- \"{1}\"", from, filename); var itemsStrings = RunCmd( Settings.GitCommand, blameCommand ) .Split('\n'); GitBlame blame = new GitBlame(); GitBlameHeader blameHeader = null; GitBlameLine blameLine = null; for (int i = 0; i < itemsStrings.GetLength(0); i++) { try { string line = itemsStrings[i]; //The contents of the actual line is output after the above header, prefixed by a TAB. This is to allow adding more header elements later. if (line.StartsWith("\t")) blameLine.LineText = line.Substring(1).Trim(new char[] { '\r' });//trim first tab else if (line.StartsWith("author-mail")) blameHeader.AuthorMail = line.Substring("author-mail".Length).Trim(); else if (line.StartsWith("author-time")) blameHeader.AuthorTime = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(int.Parse(line.Substring("author-time".Length).Trim())); else if (line.StartsWith("author-tz")) blameHeader.AuthorTimeZone = line.Substring("author-tz".Length).Trim(); else if (line.StartsWith("author")) { blameHeader = new GitBlameHeader(); blameHeader.CommitGuid = blameLine.CommitGuid; blameHeader.Author = line.Substring("author".Length).Trim(); blame.Headers.Add(blameHeader); } else if (line.StartsWith("committer-mail")) blameHeader.CommitterMail = line.Substring("committer-mail".Length).Trim(); else if (line.StartsWith("committer-time")) blameHeader.CommitterTime = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(int.Parse(line.Substring("committer-time".Length).Trim())); else if (line.StartsWith("committer-tz")) blameHeader.CommitterTimeZone = line.Substring("committer-tz".Length).Trim(); else if (line.StartsWith("committer")) blameHeader.Committer = line.Substring("committer".Length).Trim(); else if (line.StartsWith("summary")) blameHeader.Summary = line.Substring("summary".Length).Trim(); else if (line.StartsWith("filename")) blameHeader.FileName = line.Substring("filename".Length).Trim(); else if (line.IndexOf(' ') == 40) //SHA1, create new line! { blameLine = new GitBlameLine(); blameLine.CommitGuid = line.Substring(0, 40); blame.Lines.Add(blameLine); } } catch { //Catch all parser errors, and ignore them all! //We should never get here... Settings.GitLog.Log("Error parsing output from command: " + blameCommand + "\n\nPlease report a bug!"); } } return blame; }
private void ActiveTextAreaControlDoubleClick(object sender, EventArgs e) { if (_lastBlameLine.CommitGuid == null) return; if (_revGrid != null) { _clickedBlameLine = _lastBlameLine; _revGrid.SetSelectedRevision(_lastBlameLine.CommitGuid); } else { using (var frm = new FormCommitDiff(UICommands, _lastBlameLine.CommitGuid)) frm.ShowDialog(this); } }
void SelectedLineChanged(object sender, int selectedLine) { if (_blame == null || selectedLine >= _blame.Lines.Count) return; //TODO: Request GitRevision from RevisionGrid that contain all commits var newBlameLine = _blame.Lines[selectedLine]; if (_lastBlameLine.CommitGuid == newBlameLine.CommitGuid) return; _lastBlameLine = newBlameLine; CommitInfo.RevisionGuid = _lastBlameLine.CommitGuid; }
private void ProcessBlame(GitRevision revision, List<string> children, Control controlToMask, int line, int scrollpos) { var blameCommitter = new StringBuilder(); var blameFile = new StringBuilder(); for (int i = 0; i < _blame.Lines.Count; i++) { GitBlameLine blameLine = _blame.Lines[i]; GitBlameHeader blameHeader = _blame.FindHeaderForCommitGuid(blameLine.CommitGuid); if (i > 0 && _blame.Lines[i - 1].CommitGuid == blameLine.CommitGuid) { blameCommitter.AppendLine(new string(' ', 200)); } else { blameCommitter.AppendLine( (blameHeader.Author + " - " + blameHeader.AuthorTime + " - " + blameHeader.FileName + new string(' ', 100)).Trim(new[] {'\r', '\n'})); } if (blameLine.LineText == null) blameFile.AppendLine(""); else blameFile.AppendLine(blameLine.LineText.Trim(new[] {'\r', '\n'})); } BlameCommitter.ViewText("committer.txt", blameCommitter.ToString()); BlameFile.ViewText(_fileName, blameFile.ToString()); if (line == 0) BlameFile.ScrollPos = scrollpos; else BlameFile.GoToLine(line); _clickedBlameLine = new GitBlameLine(); _blameHash = revision.Guid; CommitInfo.SetRevisionWithChildren(revision, children); if (controlToMask != null) controlToMask.UnMask(); }
private void blamePreviousRevisionToolStripMenuItem_Click(object sender, EventArgs e) { int line = (int?)contextMenu.Tag ?? -1; if (line < 0) return; string commit = _blame.Lines[line].CommitGuid; int originalLine = _blame.Lines[line].OriginLineNumber; GitBlame blame = Module.Blame(_fileName, commit + "^", originalLine + ",+1", _encoding); if (blame.Lines.Count > 0) { var revision = blame.Lines[0].CommitGuid; if (_revGrid != null) { _clickedBlameLine = blame.Lines[0]; _revGrid.SetSelectedRevision(revision); } else { using (var frm = new FormCommitDiff(UICommands, revision)) frm.ShowDialog(this); } } }