/// <summary> /// Throws ContextMakingException. /// </summary> static private IEnumerable <GitDiffSection> getDiffSections(IGitCommandService git, string sha1, string sha2, string filename1, string filename2) { List <GitDiffSection> sections = new List <GitDiffSection>(); GitDiffArguments arguments = new GitDiffArguments( GitDiffArguments.DiffMode.Context, new GitDiffArguments.CommonArguments(sha1, sha2, filename1, filename2, null), new GitDiffArguments.DiffContextArguments(0)); IEnumerable <string> diff; try { diff = git?.ShowDiff(arguments); } catch (GitNotAvailableDataException ex) { throw new ContextMakingException("Cannot obtain git diff", ex); } if (diff == null) { throw new ContextMakingException("Cannot obtain git diff", null); } foreach (string line in diff) { Match m = diffSectionRe.Match(line); if (!m.Success || m.Groups.Count < 3) { continue; } if (!m.Groups["left_start"].Success || !m.Groups["right_start"].Success) { continue; } // @@ -1 +1 @@ is essentially the same as @@ -1,1 +1,1 @@ int leftSectionStart = int.Parse(m.Groups["left_start"].Value); int leftSectionLength = m.Groups["left_len"].Success ? int.Parse(m.Groups["left_len"].Value) : 1; int rightSectionStart = int.Parse(m.Groups["right_start"].Value); int rightSectionLength = m.Groups["right_len"].Success ? int.Parse(m.Groups["right_len"].Value) : 1; GitDiffSection section = new GitDiffSection( leftSectionStart, leftSectionStart + leftSectionLength, rightSectionStart, rightSectionStart + rightSectionLength); sections.Add(section); } return(sections); }
async protected override Task doUpdate(ILocalCommitStorage repo) { foreach (KeyValuePair <MergeRequestKey, Version> keyValuePair in collectLatestVersions(repo)) { DiffStatistic?diffStat = null; if (!String.IsNullOrEmpty(keyValuePair.Value.Base_Commit_SHA) && !String.IsNullOrEmpty(keyValuePair.Value.Head_Commit_SHA)) { GitDiffArguments args = new GitDiffArguments ( GitDiffArguments.DiffMode.ShortStat, new GitDiffArguments.CommonArguments ( keyValuePair.Value.Base_Commit_SHA, keyValuePair.Value.Head_Commit_SHA, null, null, null ), null ); bool finished = repo?.Updater == null; CommitBasedContextProvider contextProvider = new CommitBasedContextProvider( new string[] { keyValuePair.Value.Head_Commit_SHA }, keyValuePair.Value.Base_Commit_SHA); repo?.Updater?.RequestUpdate(contextProvider, () => finished = true); await TaskUtils.WhileAsync(() => !finished); try { if (repo?.Git != null) { await repo.Git.FetchAsync(args); } diffStat = parseGitDiffStatistic(repo, keyValuePair.Key, args); } catch (FetchFailedException ex) { ExceptionHandlers.Handle(String.Format( "Cannot update git statistic for MR with IID {0}", keyValuePair.Key), ex); } } _statistic[keyValuePair.Key] = new MergeRequestStatistic(keyValuePair.Value.Created_At, diffStat); Update?.Invoke(); } }
private DiffStatistic?parseGitDiffStatistic(ILocalCommitStorage repo, MergeRequestKey mrk, GitDiffArguments args) { void traceError(string text) { Trace.TraceError(String.Format( "[GitBasedSizeCollector] Cannot parse git diff text {0} obtained by key {3} in the repo {2} (in \"{1}\"). " + "This makes impossible to show git statistic for MR with IID {4}", text, repo.Path, String.Format("{0}/{1}", args.CommonArgs.Sha1?.ToString() ?? "N/A", args.CommonArgs.Sha2?.ToString() ?? "N/A"), String.Format("{0}:{1}", repo.ProjectKey.HostName, repo.ProjectKey.ProjectName), mrk.IId)); } IEnumerable <string> statText = null; try { statText = repo.Git?.ShowDiff(args); } catch (GitNotAvailableDataException ex) { ExceptionHandlers.Handle("Cannot obtain git statistic", ex); } if (statText == null || !statText.Any()) { traceError(statText == null ? "\"null\"" : "(empty)"); return(null); } int parseOrZero(string x) => int.TryParse(x, out int result) ? result : 0; string firstLine = statText.First(); Match m = gitDiffStatRe.Match(firstLine); if (!m.Success || !m.Groups["files"].Success || parseOrZero(m.Groups["files"].Value) < 1) { traceError(firstLine); return(null); } return(new DiffStatistic(parseOrZero(m.Groups["files"].Value), parseOrZero(m.Groups["ins"].Value), parseOrZero(m.Groups["del"].Value))); }
/// <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 FullContextDiffProviderException("Cannot obtain git diff", ex); } if (fullDiff == null) { throw new FullContextDiffProviderException("Cannot obtain git diff", null); } fullDiff = fullDiff.Where(x => !String.IsNullOrEmpty(x)); 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; } string 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); }