Пример #1
0
            static string GetSelectedPatch(
                FileViewer fileViewer,
                ObjectId firstId,
                ObjectId selectedId,
                GitItemStatus file)
            {
                if (firstId == ObjectId.CombinedDiffId)
                {
                    var diffOfConflict = fileViewer.Module.GetCombinedDiffContent(selectedId, file.Name,
                                                                                  fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                    return(string.IsNullOrWhiteSpace(diffOfConflict)
                        ? Strings.UninterestingDiffOmitted
                        : diffOfConflict);
                }

                if (file.IsSubmodule && file.GetSubmoduleStatusAsync() is not null)
                {
                    // Patch already evaluated
                    var status = ThreadHelper.JoinableTaskFactory.Run(file.GetSubmoduleStatusAsync);
                    return(status is not null
                        ? LocalizationHelpers.ProcessSubmoduleStatus(fileViewer.Module, status)
                        : $"Failed to get status for submodule \"{file.Name}\"");
                }

                var patch = GetItemPatch(fileViewer.Module, file, firstId, selectedId,
                                         fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                return(file.IsSubmodule
                    ? LocalizationHelpers.ProcessSubmodulePatch(fileViewer.Module, file.Name, patch)
                    : patch?.Text);
            static string?GetSelectedPatch(
                FileViewer fileViewer,
                ObjectId firstId,
                ObjectId selectedId,
                GitItemStatus file)
            {
                if (firstId == ObjectId.CombinedDiffId)
                {
                    var diffOfConflict = fileViewer.Module.GetCombinedDiffContent(selectedId, file.Name,
                                                                                  fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                    return(string.IsNullOrWhiteSpace(diffOfConflict)
                        ? TranslatedStrings.UninterestingDiffOmitted
                        : diffOfConflict);
                }

                if (file.IsSubmodule)
                {
#pragma warning disable VSTHRD103 // Call async methods when in an async method
                    var status = ThreadHelper.JoinableTaskFactory.Run(file.GetSubmoduleStatusAsync !);
#pragma warning restore VSTHRD103 // Call async methods when in an async method
                    return(status is not null
                        ? LocalizationHelpers.ProcessSubmoduleStatus(fileViewer.Module, status)
                        : $"Failed to get status for submodule \"{file.Name}\"");
                }

                var patch = GetItemPatch(fileViewer.Module, file, firstId, selectedId,
                                         fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                return(file.IsSubmodule
                    ? LocalizationHelpers.ProcessSubmodulePatch(fileViewer.Module, file.Name, patch)
                    : patch?.Text);
Пример #3
0
        public static string GetSelectedPatch(this FileViewer diffViewer, string firstRevision, string secondRevision, GitItemStatus file)
        {
            if (!file.IsTracked)
            {
                var fullPath = Path.Combine(diffViewer.Module.WorkingDir, file.Name);
                if (Directory.Exists(fullPath) && GitModule.IsValidGitWorkingDir(fullPath))
                {
                    // git-status does not detect details for untracked and git-diff --no-index will not give info
                    return(LocalizationHelpers.GetSubmoduleText(diffViewer.Module, file.Name.TrimEnd('/'), ""));
                }
            }

            if (file.IsSubmodule && file.SubmoduleStatus != null)
            {
                return(LocalizationHelpers.ProcessSubmoduleStatus(diffViewer.Module, file.SubmoduleStatus.Result));
            }

            PatchApply.Patch patch = GetItemPatch(diffViewer.Module, file, firstRevision, secondRevision,
                                                  diffViewer.GetExtraDiffArguments(), diffViewer.Encoding);

            if (patch == null)
            {
                return(string.Empty);
            }

            if (file.IsSubmodule)
            {
                return(LocalizationHelpers.ProcessSubmodulePatch(diffViewer.Module, file.Name, patch));
            }

            return(patch.Text);
        }
Пример #4
0
            static async Task <string?> GetSelectedPatchAsync(
                FileViewer fileViewer,
                ObjectId firstId,
                ObjectId selectedId,
                GitItemStatus file,
                CancellationToken cancellationToken)
            {
                if (firstId == ObjectId.CombinedDiffId)
                {
                    var diffOfConflict = fileViewer.Module.GetCombinedDiffContent(selectedId, file.Name,
                                                                                  fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                    cancellationToken.ThrowIfCancellationRequested();
                    return(string.IsNullOrWhiteSpace(diffOfConflict)
                        ? TranslatedStrings.UninterestingDiffOmitted
                        : diffOfConflict);
                }

                var task = file.GetSubmoduleStatusAsync();

                if (file.IsSubmodule && task is not null)
                {
                    // Patch already evaluated
                    var status = await task;

                    cancellationToken.ThrowIfCancellationRequested();
                    return(status is not null
                        ? LocalizationHelpers.ProcessSubmoduleStatus(fileViewer.Module, status)
                        : $"Failed to get status for submodule \"{file.Name}\"");
                }

                var patch = await GetItemPatchAsync(fileViewer.Module, file, firstId, selectedId,
                                                    fileViewer.GetExtraDiffArguments(), fileViewer.Encoding);

                cancellationToken.ThrowIfCancellationRequested();
                return(file.IsSubmodule
                    ? LocalizationHelpers.ProcessSubmodulePatch(fileViewer.Module, file.Name, patch)
                    : patch?.Text);
Пример #5
0
        public static string GetSelectedPatch(this FileViewer diffViewer, string firstRevision, string secondRevision, GitItemStatus file)
        {
            if (firstRevision == null)
            {
                return(null);
            }

            //to simplify if-ology
            if (GitRevision.IsArtificial(secondRevision) && firstRevision != GitRevision.UnstagedGuid)
            {
                string temp = firstRevision;
                firstRevision  = secondRevision;
                secondRevision = temp;
            }

            if (IsItemUntracked(file, firstRevision, secondRevision))
            {
                var fullPath = Path.Combine(diffViewer.Module.WorkingDir, file.Name);
                if (Directory.Exists(fullPath) && GitModule.IsValidGitWorkingDir(fullPath))
                {
                    return(LocalizationHelpers.GetSubmoduleText(diffViewer.Module, file.Name.TrimEnd('/'), ""));
                }
                return(FileReader.ReadFileContent(fullPath, diffViewer.Encoding));
            }

            if (file.IsSubmodule && file.SubmoduleStatus != null)
            {
                return(LocalizationHelpers.ProcessSubmoduleStatus(diffViewer.Module, file.SubmoduleStatus.Result));
            }

            PatchApply.Patch patch = GetItemPatch(diffViewer.Module, file, firstRevision, secondRevision,
                                                  diffViewer.GetExtraDiffArguments(), diffViewer.Encoding);

            if (patch == null)
            {
                return(string.Empty);
            }

            if (file.IsSubmodule)
            {
                return(LocalizationHelpers.ProcessSubmodulePatch(diffViewer.Module, file.Name, patch));
            }
            return(patch.Text);
        }
Пример #6
0
        private static string GetSelectedPatch(
            [NotNull] this FileViewer diffViewer,
            [CanBeNull] ObjectId firstRevision,
            [CanBeNull] ObjectId secondRevision,
            [NotNull] GitItemStatus file)
        {
            if (!file.IsTracked)
            {
                var fullPath = Path.Combine(diffViewer.Module.WorkingDir, file.Name);
                if (Directory.Exists(fullPath) && GitModule.IsValidGitWorkingDir(fullPath))
                {
                    // git-status does not detect details for untracked and git-diff --no-index will not give info
                    return(LocalizationHelpers.GetSubmoduleText(diffViewer.Module, file.Name.TrimEnd('/'), ""));
                }
            }

            if (file.IsSubmodule && file.GetSubmoduleStatusAsync() != null)
            {
                return(LocalizationHelpers.ProcessSubmoduleStatus(diffViewer.Module, ThreadHelper.JoinableTaskFactory.Run(() => file.GetSubmoduleStatusAsync())));
            }

            Patch patch = GetItemPatch(diffViewer.Module, file, firstRevision, secondRevision,
                                       diffViewer.GetExtraDiffArguments(), diffViewer.Encoding);

            if (patch == null)
            {
                return(string.Empty);
            }

            if (file.IsSubmodule)
            {
                return(LocalizationHelpers.ProcessSubmodulePatch(diffViewer.Module, file.Name, patch));
            }

            return(patch.Text);
        }
Пример #7
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 Task ViewChangesAsync(this FileViewer fileViewer,
                                            [CanBeNull] FileStatusItem item,
                                            [NotNull] string defaultText        = "",
                                            [CanBeNull] Action openWithDiffTool = null)
        {
            if (item?.Item?.IsStatusOnly ?? false)
            {
                // Present error (e.g. parsing Git)
                return(fileViewer.ViewTextAsync(item.Item.Name, item.Item.ErrorMessage));
            }

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

                fileViewer.Clear();
                return(Task.CompletedTask);
            }

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

            openWithDiffTool ??= OpenWithDiffTool;

            if (item.Item.IsNew || firstId is null || FileHelper.IsImage(item.Item.Name))
            {
                // View blob guid from revision, or file for worktree
                return(fileViewer.ViewGitItemRevisionAsync(item.Item, item.SecondRevision.ObjectId, openWithDiffTool));
            }

            if (item.Item.IsRangeDiff)
            {
                // This command may take time, give an indication of what is going on
                // The sha are incorrect if baseA/baseB is set, to simplify the presentation
                fileViewer.ViewText("range-diff.sh", $"git range-diff {firstId}...{item.SecondRevision.ObjectId}");

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

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

                return(fileViewer.ViewRangeDiffAsync(filename, output ?? defaultText));
            }

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

            return(item.Item.IsSubmodule
                ? fileViewer.ViewTextAsync(item.Item.Name, text: selectedPatch, openWithDifftool: openWithDiffTool)
                : fileViewer.ViewPatchAsync(item, text: selectedPatch, openWithDifftool: openWithDiffTool));

            void OpenWithDiffTool()
            {
                fileViewer.Module.OpenWithDifftool(
                    item.Item.Name,
                    item.Item.OldName,
                    firstId?.ToString(),
                    item.SecondRevision.ToString(),
                    isTracked: item.Item.IsTracked);
            }
Пример #8
0
        public static string GetSelectedPatch(this FileViewer diffViewer, RevisionGrid grid, GitItemStatus file)
        {
            IList <GitRevision> revisions = grid.GetSelectedRevisions();

            if (revisions.Count == 0)
            {
                return(null);
            }

            string firstRevision  = revisions[0].Guid;
            var    secondRevision = revisions.Count == 2 ? revisions[1].Guid : null;

            //to simplify if-ology
            if (GitRevision.IsArtificial(secondRevision) && firstRevision != GitRevision.UncommittedWorkingDirGuid)
            {
                firstRevision  = secondRevision;
                secondRevision = revisions[0].Guid;
            }

            string extraDiffArgs = null;

            if (firstRevision == GitRevision.UncommittedWorkingDirGuid) //working dir changes
            {
                if (secondRevision == null || secondRevision == GitRevision.IndexGuid)
                {
                    if (file.IsTracked)
                    {
                        return(ProcessDiffText(GitModule.Current.GetCurrentChanges(file.Name, file.OldName, false,
                                                                                   diffViewer.GetExtraDiffArguments(), diffViewer.Encoding), file.IsSubmodule));
                    }

                    return(FileReader.ReadFileContent(GitModule.CurrentWorkingDir + file.Name, diffViewer.Encoding));
                }
                else
                {
                    firstRevision  = secondRevision;
                    secondRevision = string.Empty;
                }
            }
            if (firstRevision == GitRevision.IndexGuid) //index
            {
                if (secondRevision == null)
                {
                    return(ProcessDiffText(GitModule.Current.GetCurrentChanges(file.Name, file.OldName, true,
                                                                               diffViewer.GetExtraDiffArguments(), diffViewer.Encoding), file.IsSubmodule));
                }

                //rev1 vs index
                firstRevision  = secondRevision;
                secondRevision = string.Empty;
                extraDiffArgs  = string.Join(" ", extraDiffArgs, "--cached");
            }

            Debug.Assert(!GitRevision.IsArtificial(firstRevision), string.Join(" ", firstRevision, secondRevision));

            if (secondRevision == null)
            {
                secondRevision = firstRevision + "^";
            }

            PatchApply.Patch patch = GitModule.Current.GetSingleDiff(firstRevision, secondRevision, file.Name, file.OldName,
                                                                     string.Join(" ", diffViewer.GetExtraDiffArguments(), extraDiffArgs), diffViewer.Encoding);

            if (patch == null)
            {
                return(string.Empty);
            }

            return(ProcessDiffText(patch.Text, file.IsSubmodule));
        }
        /// <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;
                }

                fileViewer.Clear();
                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("range-diff.sh", $"git range-diff {range}");

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

                // 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))
                                   ?? 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);
            }