Beispiel #1
0
        /// <summary>
        /// View the changes between the revisions, if possible as a diff.
        /// </summary>
        /// <param name="fileViewer">Current FileViewer.</param>
        /// <param name="item">The FileStatusItem to present changes for.</param>
        /// <param name="defaultText">default text if no diff is possible.</param>
        /// <param name="openWithDiffTool">The difftool command to open with.</param>
        /// <returns>Task to view.</returns>
        public static async Task ViewChangesAsync(this FileViewer fileViewer,
                                                  FileStatusItem?item,
                                                  CancellationToken cancellationToken,
                                                  string defaultText      = "",
                                                  Action?openWithDiffTool = null)
        {
            if (item?.Item.IsStatusOnly ?? false)
            {
                // Present error (e.g. parsing Git)
                await fileViewer.ViewTextAsync(item.Item.Name, item.Item.ErrorMessage ?? "");

                return;
            }

            if (item?.Item is null || item.SecondRevision?.ObjectId is null)
            {
                if (!string.IsNullOrWhiteSpace(defaultText))
                {
                    await fileViewer.ViewTextAsync(item?.Item?.Name, defaultText);

                    return;
                }

                await fileViewer.ClearAsync();

                return;
            }

            var firstId = item.FirstRevision?.ObjectId ?? item.SecondRevision.FirstParentId;

            openWithDiffTool ??= OpenWithDiffTool;

            if (item.Item.IsNew || firstId is null || (!item.Item.IsDeleted && FileHelper.IsImage(item.Item.Name)))
            {
                // View blob guid from revision, or file for worktree
                await fileViewer.ViewGitItemAsync(item, openWithDiffTool);

                return;
            }

            if (item.Item.IsRangeDiff)
            {
                // Git range-diff has cubic runtime complexity and can be slow and memory consuming,
                // give an indication of what is going on
                string range = item.BaseA is null || item.BaseB is null
                    ? $"{firstId}...{item.SecondRevision.ObjectId}"
                    : $"{item.BaseA}..{firstId} {item.BaseB}..{item.SecondRevision.ObjectId}";

                await fileViewer.ViewTextAsync("git-range-diff.sh", $"git range-diff {range}");

                string output = await fileViewer.Module.GetRangeDiffAsync(
                    firstId,
                    item.SecondRevision.ObjectId,
                    item.BaseA,
                    item.BaseB,
                    fileViewer.GetExtraDiffArguments(isRangeDiff: true),
                    cancellationToken);

                // Try set highlighting from first found filename
                Match  match    = new Regex(@"\n\s*(@@|##)\s+(?<file>[^#:\n]+)").Match(output ?? "");
                string filename = match.Groups["file"].Success ? match.Groups["file"].Value : item.Item.Name;

                cancellationToken.ThrowIfCancellationRequested();

                await fileViewer.ViewRangeDiffAsync(filename, output ?? defaultText);

                return;
            }

            string selectedPatch = (await GetSelectedPatchAsync(fileViewer, firstId, item.SecondRevision.ObjectId, item.Item, cancellationToken))
                                   ?? defaultText;

            cancellationToken.ThrowIfCancellationRequested();

            if (item.Item.IsSubmodule)
            {
                await fileViewer.ViewTextAsync(item.Item.Name, text : selectedPatch, openWithDifftool : openWithDiffTool);
            }
            else
            {
                await fileViewer.ViewPatchAsync(item, text : selectedPatch, openWithDifftool : openWithDiffTool);
            }

            return;

            void OpenWithDiffTool()
            {
                fileViewer.Module.OpenWithDifftool(
                    item.Item.Name,
                    item.Item.OldName,
                    firstId?.ToString(),
                    item.SecondRevision.ToString(),
                    isTracked: item.Item.IsTracked);
            }