Beispiel #1
0
        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));
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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;
        }
Beispiel #7
0
 /// <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);
     }
 }
Beispiel #8
0
        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();
        }
Beispiel #9
0
        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);
            }
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
 /// <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));
 }
Beispiel #12
0
        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;
        }
Beispiel #13
0
 /// <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);
 }
Beispiel #14
0
        /// <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);
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
 /// <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));
 }