/// <summary> /// Throws ArgumentException, ContextMakingException. /// </summary> public DiffContext GetContext(DiffPosition position, ContextDepth depth) { if (!Context.Helpers.IsValidPosition(position)) { throw new ArgumentException( String.Format("Bad \"position\": {0}", position.ToString())); } if (!Context.Helpers.IsValidContextDepth(depth)) { throw new ArgumentException( String.Format("Bad \"depth\": {0}", depth.ToString())); } // If RightLine is valid, then it points to either added/modified or unchanged line, handle them the same way bool isRightSideContext = position.RightLine != null; int linenumber = isRightSideContext ? int.Parse(position.RightLine) : int.Parse(position.LeftLine); string leftFilename = position.LeftPath; string rightFilename = position.RightPath; string leftSHA = position.Refs.LeftSHA; string rightSHA = position.Refs.RightSHA; FullContextDiffProvider provider = new FullContextDiffProvider(_git); FullContextDiff context = provider.GetFullContextDiff(leftSHA, rightSHA, leftFilename, rightFilename); Debug.Assert(context.Left.Count == context.Right.Count); if (linenumber > context.Left.Count) { throw new ArgumentException( String.Format("Line number {0} is greater than total line number count, invalid \"position\": {1}", linenumber.ToString(), position.ToString())); } return(createDiffContext(linenumber, isRightSideContext, context, depth)); }
/// <summary> /// Throws GitOperationException in case of problems with git. /// </summary> public FullContextDiff GetFullContextDiff(string leftSHA, string rightSHA, string leftFileName, string rightFileName) { FullContextDiff fullContextDiff = new FullContextDiff { Left = new SparsedList <string>(), Right = new SparsedList <string>() }; List <string> fullDiff = _gitRepository.Diff(leftSHA, rightSHA, leftFileName, rightFileName, maxDiffContext); if (fullDiff.Count == 0) { Trace.TraceWarning(String.Format( "[FullContextDiffProvider] Context size is zero. LeftSHA: {0}, Right SHA: {1}, Left file: {2}, Right file: {3}", leftSHA, rightSHA, leftFileName, rightFileName)); } bool skip = true; foreach (string line in fullDiff) { char sign = line[0]; if (skip) { // skip meta information about diff if (sign == '@') { // next lines should not be skipped because they contain a diff itself skip = false; } continue; } var lineOrig = line.Substring(1, line.Length - 1); switch (sign) { case '-': fullContextDiff.Left.Add(lineOrig); fullContextDiff.Right.Add(null); break; case '+': fullContextDiff.Left.Add(null); fullContextDiff.Right.Add(lineOrig); break; case ' ': fullContextDiff.Left.Add(lineOrig); fullContextDiff.Right.Add(lineOrig); break; } } return(fullContextDiff); }
/// <summary> /// Throws ArgumentException, ContextMakingException. /// </summary> public DiffContext GetContext(DiffPosition position, ContextDepth depth, UnchangedLinePolicy unchangedLinePolicy) { if (!Context.Helpers.IsValidPosition(position)) { throw new ArgumentException( String.Format("Bad \"position\": {0}", position.ToString())); } if (!Context.Helpers.IsValidContextDepth(depth)) { throw new ArgumentException( String.Format("Bad \"depth\": {0}", depth.ToString())); } bool isRightSideContext = Helpers.IsRightSidePosition(position, unchangedLinePolicy); int linenumber = isRightSideContext ? Helpers.GetRightLineNumber(position) : Helpers.GetLeftLineNumber(position); string leftFilename = position.LeftPath; string rightFilename = position.RightPath; string leftSHA = position.Refs.LeftSHA; string rightSHA = position.Refs.RightSHA; try { FullContextDiff context = _git.FullContextDiffProvider.GetFullContextDiff( leftSHA, rightSHA, leftFilename, rightFilename); Debug.Assert(context.Left.Count == context.Right.Count); if (linenumber > context.Left.Count) { throw new ArgumentException( String.Format("Line number {0} is greater than total line number count, invalid \"position\": {1}", linenumber.ToString(), position.ToString())); } return(createDiffContext(linenumber, isRightSideContext, context, depth)); } catch (FullContextDiffProviderException ex) { throw new ContextMakingException("Cannot obtain full context diff", ex); } }
/// <summary> /// Throws ContextMakingException. /// </summary> public FullContextDiff GetFullContextDiff(string leftSHA, string rightSHA, string leftFileName, string rightFileName) { FullContextDiff fullContextDiff = new FullContextDiff(new SparsedList <string>(), new SparsedList <string>()); GitDiffArguments arguments = new GitDiffArguments( GitDiffArguments.DiffMode.Context, new GitDiffArguments.CommonArguments(leftSHA, rightSHA, leftFileName, rightFileName, null), new GitDiffArguments.DiffContextArguments(Constants.FullContextSize)); IEnumerable <string> fullDiff; try { fullDiff = _git?.ShowDiff(arguments); } catch (GitNotAvailableDataException ex) { throw new ContextMakingException("Cannot obtain git diff", ex); } if (fullDiff == null) { throw new ContextMakingException("Cannot obtain git diff", null); } if (fullDiff.Count() == 0) { Trace.TraceWarning(String.Format( "[FullContextDiffProvider] Context size is zero. LeftSHA: {0}, Right SHA: {1}, Left file: {2}, Right file: {3}", leftSHA, rightSHA, leftFileName, rightFileName)); } bool skip = true; foreach (string line in fullDiff) { char sign = line[0]; if (skip) { // skip meta information about diff if (sign == '@') { // next lines should not be skipped because they contain a diff itself skip = false; } continue; } var lineOrig = line.Substring(1, line.Length - 1); switch (sign) { case '-': fullContextDiff.Left.Add(lineOrig); fullContextDiff.Right.Add(null); break; case '+': fullContextDiff.Left.Add(null); fullContextDiff.Right.Add(lineOrig); break; case ' ': fullContextDiff.Left.Add(lineOrig); fullContextDiff.Right.Add(lineOrig); break; } } return(fullContextDiff); }
// isRightSideContext is true when linenumber corresponds to the right side (sha2). // linenumber is one-based private DiffContext createDiffContext(int linenumber, bool isRightSideContext, FullContextDiff context, ContextDepth depth) { int startLineNumber = Math.Max(1, linenumber - depth.Up); int endLineNumber = linenumber + depth.Down; SparsedListIterator <string> itLeft = context.Left.Begin(); SparsedListIterator <string> itRight = context.Right.Begin(); if (isRightSideContext) { itRight = SparsedListUtils.FindNth(itRight, startLineNumber - 1); itLeft = SparsedListUtils.Advance(itLeft, itRight.Position); } else { itLeft = SparsedListUtils.FindNth(itLeft, startLineNumber - 1); itRight = SparsedListUtils.Advance(itRight, itLeft.Position); } int iContextLine = 0; int selectedIndex = 0; List <DiffContext.Line> lines = new List <DiffContext.Line>(); while (true) { int?leftLineNumber = itLeft.GetLineNumber() != null?itLeft.GetLineNumber() + 1 : null; int?rightLineNumber = itRight.GetLineNumber() != null?itRight.GetLineNumber() + 1 : null; DiffContext.Line line = getLineContext(leftLineNumber, rightLineNumber, itLeft.GetCurrent(), itRight.GetCurrent()); lines.Add(line); if ((leftLineNumber.HasValue && !isRightSideContext && leftLineNumber == linenumber) || (rightLineNumber.HasValue && isRightSideContext && rightLineNumber == linenumber)) { // zero-based index of a selected line in DiffContext.Lines selectedIndex = iContextLine; } if ((leftLineNumber.HasValue && !isRightSideContext && leftLineNumber >= endLineNumber) || (rightLineNumber.HasValue && isRightSideContext && rightLineNumber >= endLineNumber)) { // we've just reached a line that should not be included in the context break; } if (!itLeft.Next() || !itRight.Next()) { // we've just reached the end break; } ++iContextLine; } return(new DiffContext(lines, selectedIndex)); }