private Patch GetDiffPatch(Repository repo, Commit commit) { var compareOption = new CompareOptions { Algorithm = DiffAlgorithm.Minimal, Similarity = new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.Renames } }; // grab the parent var parent = commit.Parents.FirstOrDefault(); return(repo.Diff.Compare <Patch>(parent?.Tree, commit.Tree, compareOption)); }
/// <summary> /// Show changes between two <see cref="Tree"/>s. /// </summary> /// <param name="oldTree">The <see cref="Tree"/> you want to compare from.</param> /// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define comparison behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns> public virtual TreeChanges Compare(Tree oldTree, Tree newTree, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = TreeToTree(repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; ObjectId newTreeId = newTree != null ? newTree.Id : null; var diffOptions = DiffModifiers.None; if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return BuildTreeChangesFromComparer(oldTreeId, newTreeId, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); }
private static Patch GetPatchInfo(Repository repo, Commit commit) { var parentCommitCount = commit.Parents?.Count() ?? 0; var compareOption = new LibGit2Sharp.CompareOptions() { Algorithm = DiffAlgorithm.Minimal, Similarity = new SimilarityOptions() { RenameDetectionMode = RenameDetectionMode.Renames } }; if (parentCommitCount <= 0) { return(repo.Diff.Compare <Patch>(null, commit.Tree, compareOption)); } else if (commit.Parents.Count() == 1) { return(repo.Diff.Compare <Patch>(commit.Parents.First().Tree, commit.Tree, compareOption)); } return(null); }
internal virtual TreeChanges Compare(DiffModifiers diffOptions, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return BuildTreeChangesFromComparer(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); }
private CommitModel ToCommitModel(Commit commit, string referenceName, bool isTree = true, string detailFilter = null, Tree compareWith = null) { if (commit == null) { return(null); } var model = new CommitModel { ReferenceName = referenceName, Sha = commit.Sha, CommitMessageShort = commit.MessageShort.RepetitionIfEmpty(UnknowString), CommitMessage = commit.Message.RepetitionIfEmpty(UnknowString), Author = commit.Author, Committer = commit.Committer, Parents = commit.Parents.Select(e => e.Sha).ToArray(), }; if (detailFilter != null) { if (detailFilter != "" && isTree) { detailFilter = detailFilter + "/"; } var firstTree = compareWith != null ? commit.Tree : commit.Parents.Any() ? commit.Parents.First().Tree : null; if (compareWith == null) { compareWith = commit.Tree; } var compareOptions = new LibGit2Sharp.CompareOptions { Similarity = SimilarityOptions.Renames, }; var paths = detailFilter == "" ? null : new[] { detailFilter }; var changes = _repository.Diff.Compare <TreeChanges>(firstTree, compareWith, paths, compareOptions: compareOptions); var patches = _repository.Diff.Compare <Patch>(firstTree, compareWith, paths, compareOptions: compareOptions); model.Changes = (from s in changes where (s.Path.Replace('\\', '/') + '/').StartsWith(detailFilter) orderby s.Path let patch = patches[s.Path] select new CommitChangeModel { //Name = s.Name, OldPath = s.OldPath.Replace('\\', '/'), Path = s.Path.Replace('\\', '/'), ChangeKind = s.Status, LinesAdded = patch.LinesAdded, LinesDeleted = patch.LinesDeleted, Patch = patch.Patch, }) .ToArray(); } return(model); }
private CommitModel ToCommitModel(Commit commit, string referenceName, bool isTree = true, string detailFilter = null, Tree compareWith = null) { if (commit == null) return null; var model = new CommitModel { ReferenceName = referenceName, Sha = commit.Sha, CommitMessageShort = commit.MessageShort.RepetitionIfEmpty(NoCommitMessage), CommitMessage = commit.Message.RepetitionIfEmpty(NoCommitMessage), Author = commit.Author, Committer = commit.Committer, Parents = commit.Parents.Select(e => e.Sha).ToArray(), }; if (detailFilter != null) { if (detailFilter != "" && isTree) detailFilter = detailFilter + "/"; var firstTree = compareWith != null ? commit.Tree : commit.Parents.Any() ? commit.Parents.First().Tree : null; if (compareWith == null) compareWith = commit.Tree; var compareOptions = new LibGit2Sharp.CompareOptions { Similarity = SimilarityOptions.Renames, }; var paths = detailFilter == "" ? null : new[] { detailFilter }; var changes = _repository.Diff.Compare<TreeChanges>(firstTree, compareWith, paths, compareOptions: compareOptions); var patches = _repository.Diff.Compare<Patch>(firstTree, compareWith, paths, compareOptions: compareOptions); model.Changes = (from s in changes where (s.Path.Replace('\\', '/') + '/').StartsWith(detailFilter) orderby s.Path let patch = patches[s.Path] select new CommitChangeModel { //Name = s.Name, OldPath = s.OldPath.Replace('\\', '/'), Path = s.Path.Replace('\\', '/'), ChangeKind = s.Status, LinesAdded = patch.LinesAdded, LinesDeleted = patch.LinesDeleted, Patch = patch.Patch, }) .ToArray(); } return model; }
/// <summary> /// Show changes between two <see cref="Blob"/>s. /// </summary> /// <param name="oldBlob">The <see cref="Blob"/> you want to compare from.</param> /// <param name="newBlob">The <see cref="Blob"/> you want to compare to.</param> /// <param name="compareOptions">Additional options to define comparison behavior.</param> /// <returns>A <see cref="ContentChanges"/> containing the changes between the <paramref name="oldBlob"/> and the <paramref name="newBlob"/>.</returns> public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob, CompareOptions compareOptions = null) { using (GitDiffOptions options = BuildOptions(DiffModifiers.None, compareOptions: compareOptions)) { return new ContentChanges(repo, oldBlob, newBlob, options); } }
private void UpdateRepository() { _repository?.Dispose(); _repository = new Repository(_repositoryPath); var compareOptions = new CompareOptions(); compareOptions.ContextLines = _fullFileDiff ? int.MaxValue : _contextLines; var tipTree = _repository.Head.Tip?.Tree; var changes = _viewStage ? _repository.Diff.Compare<TreeChanges>(tipTree, DiffTargets.Index) : _repository.Diff.Compare<TreeChanges>(null, true); var paths = changes.Select(c => c.Path).ToArray(); var patch = paths.Any() ? _viewStage ? _repository.Diff.Compare<Patch>(tipTree, DiffTargets.Index, paths, null, compareOptions) : _repository.Diff.Compare<Patch>(paths, true, null, compareOptions) : null; _document = PatchDocument.Parse(patch); _view.Document = _document; UpdateHeader(); UpdateFooter(); }
private TreeChanges BuildTreeChangesFromComparer( ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var matchedPaths = new MatchedPathsAggregator(); var filePaths = repo.ToFilePaths(paths); using (GitDiffOptions options = BuildOptions(diffOptions, filePaths, matchedPaths, compareOptions)) using (DiffListSafeHandle diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options)) { if (explicitPathsOptions != null) { DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } return new TreeChanges(diffList); } }
private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] filePaths = null, MatchedPathsAggregator matchedPathsAggregator = null, CompareOptions compareOptions = null) { var options = new GitDiffOptions(); options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE; compareOptions = compareOptions ?? new CompareOptions(); options.ContextLines = (ushort)compareOptions.ContextLines; options.InterhunkLines = (ushort)compareOptions.InterhunkLines; if (diffOptions.HasFlag(DiffModifiers.IncludeUntracked)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | GitDiffOptionFlags.GIT_DIFF_SHOW_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_IGNORED | GitDiffOptionFlags.GIT_DIFF_RECURSE_IGNORED_DIRS; } if (diffOptions.HasFlag(DiffModifiers.IncludeUnmodified) || compareOptions.IncludeUnmodified || (compareOptions.Similarity != null && (compareOptions.Similarity.RenameDetectionMode == RenameDetectionMode.CopiesHarder || compareOptions.Similarity.RenameDetectionMode == RenameDetectionMode.Exact))) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNMODIFIED; } if (compareOptions.Algorithm == DiffAlgorithm.Patience) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_PATIENCE; } else if (compareOptions.Algorithm == DiffAlgorithm.Minimal) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_MINIMAL; } if (diffOptions.HasFlag(DiffModifiers.DisablePathspecMatch)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; } if (filePaths != null) { options.PathSpec = GitStrArrayManaged.BuildFrom(filePaths); } return(options); }
/// <summary> /// Show changes between two <see cref="Tree"/>s. /// </summary> /// <param name="oldTree">The <see cref="Tree"/> you want to compare from.</param> /// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="compareOptions">Additional options to define patch generation behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns> public virtual T Compare <T>(Tree oldTree, Tree newTree, IEnumerable <string> paths, CompareOptions compareOptions) where T : class, IDiffResult { return(Compare <T>(oldTree, newTree, paths, null, compareOptions)); }
private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] filePaths = null, MatchedPathsAggregator matchedPathsAggregator = null, CompareOptions compareOptions = null) { var options = new GitDiffOptions(); options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE; compareOptions = compareOptions ?? new CompareOptions(); options.ContextLines = (ushort)compareOptions.ContextLines; options.InterhunkLines = (ushort)compareOptions.InterhunkLines; if (diffOptions.HasFlag(DiffModifiers.IncludeUntracked)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_IGNORED; } if (diffOptions.HasFlag(DiffModifiers.IncludeUnmodified)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNMODIFIED; } if (diffOptions.HasFlag(DiffModifiers.DisablePathspecMatch)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; } if (filePaths == null) { return options; } options.PathSpec = GitStrArrayIn.BuildFrom(filePaths); return options; }
/// <summary> /// Show changes between the working directory and the index. /// </summary> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="includeUntracked">If true, include untracked files from the working dir as additions. Otherwise ignore them.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define comparison behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the working directory and the index.</returns> public virtual TreeChanges Compare(IEnumerable<string> paths = null, bool includeUntracked = false, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { return Compare(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths, explicitPathsOptions, compareOptions); }
/// <summary> /// Show changes between a <see cref="Tree"/> and the Index, the Working Directory, or both. /// </summary> /// <param name="oldTree">The <see cref="Tree"/> to compare from.</param> /// <param name="diffTargets">The targets to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define comparison behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns> public virtual TreeChanges Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = handleRetrieverDispatcher[diffTargets](repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; DiffModifiers diffOptions = diffTargets.HasFlag(DiffTargets.WorkingDirectory) ? DiffModifiers.IncludeUntracked : DiffModifiers.None; if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return BuildTreeChangesFromComparer(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); }
private void ConfigureLineChanges(IObservable<Branch> activeBranch) { var lineChanges = activeBranch.Merge(fileSystem.ThrottleFirst(TimeSpan.FromSeconds(15)).Select(c => this.currentRepositoryModel.CurrentBranch)).Select(b => { Commit lastBranchCommit = b.Tip; CompareOptions options = new CompareOptions() { IncludeUnmodified = false, ContextLines = 5, InterhunkLines = 5 }; var repo = this.currentRepositoryModel.Repository; //CommitFilter filter = new CommitFilter() { Since = b.Tip.Sha }; var patch = repo.Diff.Compare<Patch>(repo.Head.Tip.Tree, DiffTargets.WorkingDirectory); return new { Added = patch.Sum(p => p.LinesAdded), Removed = patch.Sum(p => p.LinesDeleted) }; }); this.linesAdded = lineChanges.Select(c => c.Added).ToProperty(this, a => a.LinesAdded, 0, Scheduler.Immediate); this.linesRemoved = lineChanges.Select(c => c.Removed).ToProperty(this, a => a.LinesRemoved, 0, Scheduler.Immediate); }
private static void DetectRenames(DiffSafeHandle diffList, CompareOptions compareOptions) { var similarityOptions = (compareOptions == null) ? null : compareOptions.Similarity; if (similarityOptions == null || similarityOptions.RenameDetectionMode == RenameDetectionMode.Default) { Proxy.git_diff_find_similar(diffList, null); return; } if (similarityOptions.RenameDetectionMode == RenameDetectionMode.None) { return; } var opts = new GitDiffFindOptions { RenameThreshold = (ushort)similarityOptions.RenameThreshold, RenameFromRewriteThreshold = (ushort)similarityOptions.RenameFromRewriteThreshold, CopyThreshold = (ushort)similarityOptions.CopyThreshold, BreakRewriteThreshold = (ushort)similarityOptions.BreakRewriteThreshold, RenameLimit = (UIntPtr)similarityOptions.RenameLimit, }; switch (similarityOptions.RenameDetectionMode) { case RenameDetectionMode.Exact: opts.Flags = GitDiffFindFlags.GIT_DIFF_FIND_EXACT_MATCH_ONLY | GitDiffFindFlags.GIT_DIFF_FIND_RENAMES | GitDiffFindFlags.GIT_DIFF_FIND_COPIES | GitDiffFindFlags.GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; break; case RenameDetectionMode.Renames: opts.Flags = GitDiffFindFlags.GIT_DIFF_FIND_RENAMES; break; case RenameDetectionMode.Copies: opts.Flags = GitDiffFindFlags.GIT_DIFF_FIND_RENAMES | GitDiffFindFlags.GIT_DIFF_FIND_COPIES; break; case RenameDetectionMode.CopiesHarder: opts.Flags = GitDiffFindFlags.GIT_DIFF_FIND_RENAMES | GitDiffFindFlags.GIT_DIFF_FIND_COPIES | GitDiffFindFlags.GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; break; } if (!compareOptions.IncludeUnmodified) { opts.Flags |= GitDiffFindFlags.GIT_DIFF_FIND_REMOVE_UNMODIFIED; } switch (similarityOptions.WhitespaceMode) { case WhitespaceMode.DontIgnoreWhitespace: opts.Flags |= GitDiffFindFlags.GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE; break; case WhitespaceMode.IgnoreLeadingWhitespace: opts.Flags |= GitDiffFindFlags.GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE; break; case WhitespaceMode.IgnoreAllWhitespace: opts.Flags |= GitDiffFindFlags.GIT_DIFF_FIND_IGNORE_WHITESPACE; break; } Proxy.git_diff_find_similar(diffList, opts); }
/// <summary> /// Show changes between two <see cref="Tree"/>s. /// </summary> /// <param name="oldTree">The <see cref="Tree"/> you want to compare from.</param> /// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param> /// <param name="compareOptions">Additional options to define patch generation behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns> public virtual T Compare <T>(Tree oldTree, Tree newTree, CompareOptions compareOptions) where T : class, IDiffResult { return(Compare <T>(oldTree, newTree, null, null, compareOptions)); }