internal virtual T Compare <T>( DiffModifiers diffOptions, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class, IDiffResult { var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } DiffHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); try { return(BuildDiffResult <T>(diff)); } catch { diff.SafeDispose(); throw; } }
/// <summary> /// Show changes between a <see cref="Tree"/> and the Index, the Working Directory, or both. /// <para> /// The level of diff performed can be specified by passing either a <see cref="TreeChanges"/> /// or <see cref="Patch"/> type as the generic parameter. /// </para> /// </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 patch generation behavior.</param> /// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or /// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam> /// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns> public virtual T Compare <T>(Tree oldTree, DiffTargets diffTargets, IEnumerable <string> paths, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class, IDiffResult { 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; } } DiffHandle diff = BuildDiffList(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); try { return(BuildDiffResult <T>(diff)); } catch { diff.SafeDispose(); throw; } }
/// <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 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, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class, IDiffResult { 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; } } DiffHandle diff = BuildDiffList(oldTreeId, newTreeId, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); try { return(BuildDiffResult <T>(diff)); } catch { diff.SafeDispose(); throw; } }
private static T BuildDiffResult <T>(DiffHandle diff) where T : class, IDiffResult { Func <DiffHandle, object> builder; if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) { throw new LibGit2SharpException("User-defined types passed to Compare are not supported. Supported values are: {0}", string.Join(", ", ChangesBuilders.Keys.Select(x => x.Name))); } return((T)builder(diff)); }
internal unsafe Patch(DiffHandle diff) { using (diff) { int count = Proxy.git_diff_num_deltas(diff); for (int i = 0; i < count; i++) { using (var patch = Proxy.git_patch_from_diff(diff, i)) { var delta = Proxy.git_diff_get_delta(diff, i); AddFileChange(delta); Proxy.git_patch_print(patch, PrintCallBack); } } } }
private static TreeComparisonHandleRetriever WorkdirAndIndexToTree(Repository repo) { TreeComparisonHandleRetriever comparisonHandleRetriever = (oh, nh, o) => { DiffHandle diff = Proxy.git_diff_tree_to_index(repo.Handle, repo.Index.Handle, oh, o); using (DiffHandle diff2 = Proxy.git_diff_index_to_workdir(repo.Handle, repo.Index.Handle, o)) { Proxy.git_diff_merge(diff, diff2); } return(diff); }; return(comparisonHandleRetriever); }
internal unsafe PatchStats(DiffHandle diff) { using (diff) { int count = Proxy.git_diff_num_deltas(diff); for (int i = 0; i < count; i++) { using (var patch = Proxy.git_patch_from_diff(diff, i)) { var delta = Proxy.git_diff_get_delta(diff, i); var pathPtr = delta->new_file.Path != null ? delta->new_file.Path : delta->old_file.Path; var newFilePath = LaxFilePathMarshaler.FromNative(pathPtr); var stats = Proxy.git_patch_line_stats(patch); int added = stats.Item1; int deleted = stats.Item2; changes.Add(newFilePath, new ContentChangeStats(added, deleted)); totalLinesAdded += added; totalLinesDeleted += deleted; } } } }
internal unsafe TreeChanges(DiffHandle diff) { this.diff = diff; this.count = new Lazy <int>(() => Proxy.git_diff_num_deltas(diff)); }
private static void DetectRenames(DiffHandle 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); }