/// <summary>
        /// Return DiffPosition if match succeeded and throw if match failed
        /// Throws ArgumentException in case of bad arguments.
        /// Throws MatchingException.
        /// </summary>
        public void Match(DiffRefs refs, string leftPath, string rightPath,
                          int lineNumber, bool isLeftSideLine, out string leftLineNumber, out string rightLineNumber)
        {
            int?oppositeLine;

            try
            {
                oppositeLine = getOppositeLine(refs, isLeftSideLine, leftPath, rightPath, lineNumber);
            }
            catch (BadPosition)
            {
                throw new ArgumentException(
                          String.Format("Bad position: Line Number {0} ({1})", lineNumber, isLeftSideLine ? "Left" : "Right"));
            }
            catch (FullContextDiffProviderException ex)
            {
                throw new MatchingException("Cannot match lines", ex);
            }

            string currentLineAsString  = lineNumber.ToString();
            string oppositeLineAsString = oppositeLine?.ToString();

            leftLineNumber  = isLeftSideLine ? currentLineAsString : oppositeLineAsString;
            rightLineNumber = isLeftSideLine ? oppositeLineAsString : currentLineAsString;
        }
示例#2
0
        private MatchResult match(DiffRefs diffRefs, DiffToolInfo difftoolInfo)
        {
            FullContextDiffProvider provider = new FullContextDiffProvider(_gitRepository);
            FullContextDiff         context  =
                provider.GetFullContextDiff(diffRefs.LeftSHA, diffRefs.RightSHA,
                                            difftoolInfo.Left?.FileName ?? null, difftoolInfo.Right?.FileName ?? null);

            Debug.Assert(context.Left.Count == context.Right.Count);

            bool isCurrentSideLeft = difftoolInfo.IsLeftSideCurrent;

            DiffToolInfo.Side currentSide = isCurrentSideLeft ? difftoolInfo.Left.Value : difftoolInfo.Right.Value;

            SparsedList <string> firstList  = isCurrentSideLeft ? context.Left : context.Right;
            SparsedList <string> secondList = isCurrentSideLeft ? context.Right : context.Left;

            SparsedListIterator <string> itFirst  = SparsedListUtils.FindNth(firstList.Begin(), currentSide.LineNumber - 1);
            SparsedListIterator <string> itSecond = SparsedListUtils.Advance(secondList.Begin(), itFirst.Position);

            return(new MatchResult
            {
                LeftLineNumber = isCurrentSideLeft ? currentSide.LineNumber : itSecond.LineNumber + 1,
                RightLineNumber = isCurrentSideLeft ? itSecond.LineNumber + 1 : currentSide.LineNumber
            });
        }
示例#3
0
 public DiffPosition(string leftPath, string rightPath, string leftLine, string rightLine, DiffRefs refs)
 {
     LeftPath  = leftPath;
     RightPath = rightPath;
     LeftLine  = leftLine;
     RightLine = rightLine;
     Refs      = refs;
 }
示例#4
0
 private void trace(string action, bool isLeftSide, DiffRefs refs,
                    string sourceCurrentName, string sourceOppositeName, string fixedOppositeName)
 {
     Trace.TraceInformation(String.Format(
                                "[FileNameMatcher] {0}. Repo: {1}. DiffRefs: {2}\n"
                                + "sourceCurrentName: {3}\nsourceOppositeName: {4}\nfixedOppositeName: {5}\nIsLeftSide: {6}",
                                action, _git.ToString(), refs.ToString(),
                                sourceCurrentName, sourceOppositeName, fixedOppositeName, isLeftSide));
 }
        /// <summary>
        /// Throws MatchingException.
        /// </summary>
        public bool Match(DiffRefs refs, string originalLeftFileName, string originalRightFileName, bool isLeftSideLine,
                          out string leftFileName, out string rightFileName)
        {
            string currentName  = isLeftSideLine ? originalLeftFileName : originalRightFileName;
            string oppositeName = isLeftSideLine ? originalRightFileName : originalLeftFileName;

            oppositeName  = getOppositeName(refs, isLeftSideLine, currentName, oppositeName);
            leftFileName  = isLeftSideLine ? currentName : oppositeName;
            rightFileName = isLeftSideLine ? oppositeName : currentName;
            return(oppositeName != null);
        }
示例#6
0
        /// <summary>
        /// Return DiffPosition if match succeeded and throw if match failed
        /// Throws ArgumentException in case of bad arguments.
        /// Throws GitOperationException in case of problems with git.
        /// </summary>
        public DiffPosition Match(DiffRefs diffRefs, DiffToolInfo difftoolInfo)
        {
            if (!difftoolInfo.IsValid())
            {
                throw new ArgumentException(
                          String.Format("Bad diff tool info: {0}", difftoolInfo.ToString()));
            }

            MatchResult matchResult = match(diffRefs, difftoolInfo);

            return(createPosition(matchResult, diffRefs, difftoolInfo));
        }
示例#7
0
 private void getOppositeNameInternal(DiffRefs refs, bool isLeftSide, string sourceCurrentName,
                                      out string anotherName, out bool moved)
 {
     try
     {
         anotherName = _git.RenameDetector.IsRenamed(refs.LeftSHA, refs.RightSHA,
                                                     sourceCurrentName, isLeftSide, out moved);
     }
     catch (FileRenameDetectorException ex)
     {
         throw new MatchingException("Cannot detect if a file was renamed", ex);
     }
 }
        private int?getOppositeLine(DiffRefs refs, bool isLeftSide, string leftFileName, string rightFileName,
                                    int lineNumber)
        {
            FullContextDiff context = _git.FullContextDiffProvider.GetFullContextDiff(
                refs.LeftSHA, refs.RightSHA, leftFileName, rightFileName);

            Debug.Assert(context.Left.Count == context.Right.Count);

            SparsedList <string> currentList  = isLeftSide ? context.Left : context.Right;
            SparsedList <string> oppositeList = isLeftSide ? context.Right : context.Left;

            SparsedListIterator <string> itCurrentList  = SparsedListUtils.FindNth(currentList.Begin(), lineNumber - 1);
            SparsedListIterator <string> itOppositeList = SparsedListUtils.Advance(oppositeList.Begin(), itCurrentList.Position);

            return(itOppositeList.GetLineNumber() == null ? new int?() : itOppositeList.GetLineNumber().Value + 1);
        }
示例#9
0
        private DiffPosition createPosition(MatchResult matchResult, DiffRefs diffRefs, DiffToolInfo difftoolInfo)
        {
            string leftPath  = String.Empty;
            string rightPath = String.Empty;

            getPositionPaths(ref difftoolInfo, ref leftPath, ref rightPath);

            string leftLine  = String.Empty;
            string rightLine = String.Empty;

            getPositionLines(matchResult, ref leftLine, ref rightLine);

            DiffPosition position = new DiffPosition
            {
                Refs      = diffRefs,
                LeftPath  = leftPath,
                LeftLine  = leftLine,
                RightPath = rightPath,
                RightLine = rightLine
            };

            return(position);
        }
示例#10
0
        /// <summary>
        /// Throws MatchingException.
        /// </summary>
        private string getOppositeName(DiffRefs refs, bool isLeftSide, string sourceCurrentName, string sourceOppositeName)
        {
            Debug.Assert(sourceCurrentName != String.Empty);

            getOppositeNameInternal(refs, isLeftSide, sourceCurrentName, out string anotherName, out bool moved);
            if (moved)
            {
                _onFileMove(sourceCurrentName, anotherName);
                trace("move", isLeftSide, refs, sourceCurrentName, sourceOppositeName, String.Empty);
                return(null);
            }

            Debug.Assert(anotherName != String.Empty);
            if (sourceOppositeName == String.Empty)
            {
                // nothing at the opposite side
                if (anotherName != sourceCurrentName)
                {
                    // wrong match, propose to re-match or consider new/deleted
                    if (_onFileRename(sourceCurrentName, anotherName, isLeftSide ? "deleted" : "new"))
                    {
                        // discard rename. fix up the opposite name to deceive GitLab.
                        trace("rename (continue)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, anotherName);
                        return(anotherName);
                    }
                    else
                    {
                        // user will re-match
                        trace("rename (cancel)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, String.Empty);
                        return(null);
                    }
                }
                else
                {
                    // no rename detected
                    // GitLab expects a non-empty name in this case
                    return(sourceCurrentName);
                }
            }
            else
            {
                // opposite side is not empty
                if (anotherName != sourceCurrentName)
                {
                    // rename detected
                    if (anotherName == sourceOppositeName)
                    {
                        // manually matched files, perfect match
                        return(sourceOppositeName);
                    }
                    else
                    {
                        // wrong match, propose to re-match
                        if (_onFileRename(sourceCurrentName, anotherName, "modified"))
                        {
                            // discard rename. fix up the opposite name to deceive GitLab.
                            trace("rename (continue)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, anotherName);
                            return(anotherName);
                        }
                        else
                        {
                            // user will re-match
                            trace("rename (cancel)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, String.Empty);
                            return(null);
                        }
                    }
                }
                else
                {
                    // no rename detected
                    if (sourceCurrentName != sourceOppositeName)
                    {
                        // wrong match, propose to re-match
                        if (_onWrongMatch(sourceCurrentName))
                        {
                            trace("wrong match (continue)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, sourceCurrentName);
                            return(sourceCurrentName);
                        }
                        else
                        {
                            trace("wrong match (cancel)", isLeftSide, refs, sourceCurrentName, sourceOppositeName, String.Empty);
                            return(null);
                        }
                    }
                    else
                    {
                        // it is not a rename but really modified file detected
                        return(sourceOppositeName);
                    }
                }
            }
        }