diff --git a/src/Commands/CherryPick.cs b/src/Commands/CherryPick.cs index 504769c0..95b56655 100644 --- a/src/Commands/CherryPick.cs +++ b/src/Commands/CherryPick.cs @@ -2,12 +2,12 @@ { public class CherryPick : Command { - public CherryPick(string repo, string commit, bool noCommit) + public CherryPick(string repo, string commits, bool noCommit) { var mode = noCommit ? "-n" : "--ff"; WorkingDirectory = repo; Context = repo; - Args = $"cherry-pick {mode} {commit}"; + Args = $"cherry-pick {mode} {commits}"; } } } diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index d37fa361..afff2a31 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -82,10 +82,9 @@ Verwerfen Nichts tun Stashen & wieder anwenden - Diesen Commit cherry-picken - Commit: + Cherry Pick + Commit(s): Alle Änderungen committen - Cherry Pick Stashes löschen Du versuchst alle Stashes zu löschen. Möchtest du wirklich fortfahren? Remote Repository klonen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 7b89ddce..c59189d8 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -79,10 +79,9 @@ Discard Do Nothing Stash & Reapply - Cherry-Pick This Commit - Commit: + Cherry Pick + Commit(s): Commit all changes - Cherry Pick Clear Stashes You are trying to clear all stashes. Are you sure to continue? Clone Remote Repository @@ -95,6 +94,7 @@ CLOSE Editor Cherry-Pick This Commit + Cherry-Pick ... Checkout Commit Compare with HEAD Compare with Worktree diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 1aa3f472..c8baf25f 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -83,10 +83,9 @@ Rejeter Ne rien faire Stash et Réappliquer - Cherry-Pick ce commit - Commit : + Cherry-Pick + Commit(s) : Commit tous les changements - Cherry Pick Vider les Stashes Voulez-vous vider tous les stashes. Êtes-vous sûr de vouloir continuer ? Cloner le dépôt distant diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 5a746781..df177873 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -82,10 +82,9 @@ Descartar Nada Stash & Reaplicar - Cherry-Pick Este Commit - Commit: + Cherry-Pick + Commit(s): Commitar todas as alterações - Cherry-Pick Limpar Stashes Você está tentando limpar todas as stashes. Tem certeza que deseja continuar? Clonar Repositório Remoto diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index aab30260..a6c29f8d 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -82,10 +82,9 @@ 丢弃更改 不做处理 贮藏并自动恢复 - 挑选(cherry-pick)此提交 - 提交ID : + 挑选提交 + 提交列表 : 提交变化 - 挑选提交 丢弃贮藏确认 您正在丢弃所有的贮藏,一经操作,无法回退,是否继续? 克隆远程仓库 @@ -98,6 +97,7 @@ 关闭 提交信息编辑器 挑选(cherry-pick)此提交 + 挑选(cherry-pick)... 检出此提交 与当前HEAD比较 与本地工作树比较 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index b44618ce..c55d9c33 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -82,10 +82,9 @@ 捨棄變更 不做處理 擱置變更並自動復原 - 揀選 (cherry-pick) 此提交 - 提交編號: + 揀選提交 + 提交列表: 提交變更 - 揀選提交 捨棄擱置變更確認 您正在捨棄所有的擱置變更,一經操作便無法復原,是否繼續? 複製 (clone) 遠端存放庫 @@ -98,6 +97,7 @@ 關閉 提交訊息編輯器 揀選 (cherry-pick) 此提交 + 揀選 (cherry-pick) ... 簽出 (checkout) 此提交 與目前 HEAD 比較 與本機工作區比較 diff --git a/src/ViewModels/CherryPick.cs b/src/ViewModels/CherryPick.cs index a11d835c..9f8fe882 100644 --- a/src/ViewModels/CherryPick.cs +++ b/src/ViewModels/CherryPick.cs @@ -1,10 +1,12 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; namespace SourceGit.ViewModels { public class CherryPick : Popup { - public Models.Commit Target + public List Targets { get; private set; @@ -16,10 +18,10 @@ namespace SourceGit.ViewModels set; } - public CherryPick(Repository repo, Models.Commit target) + public CherryPick(Repository repo, List targets) { _repo = repo; - Target = target; + Targets = targets; AutoCommit = true; View = new Views.CherryPick() { DataContext = this }; } @@ -27,11 +29,16 @@ namespace SourceGit.ViewModels public override Task Sure() { _repo.SetWatcherEnabled(false); - ProgressDescription = $"Cherry-Pick commit '{Target.SHA}' ..."; + ProgressDescription = $"Cherry-Pick commit(s) ..."; return Task.Run(() => { - var succ = new Commands.CherryPick(_repo.FullPath, Target.SHA, !AutoCommit).Exec(); + // Get commit SHAs reverted + var builder = new StringBuilder(); + for (int i = Targets.Count - 1; i >= 0; i--) + builder.Append($"{Targets[i].SHA} "); + + var succ = new Commands.CherryPick(_repo.FullPath, builder.ToString(), !AutoCommit).Exec(); CallUIThread(() => _repo.SetWatcherEnabled(true)); return succ; }); diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 7d3e9e2d..5c289d8c 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -1,10 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Text; using Avalonia.Controls; using Avalonia.Platform.Storage; -using Avalonia.VisualTree; using CommunityToolkit.Mvvm.ComponentModel; @@ -182,13 +182,73 @@ namespace SourceGit.ViewModels public ContextMenu MakeContextMenu(ListBox list) { - if (list.SelectedItems.Count != 1) - return null; - var current = _repo.CurrentBranch; if (current == null) return null; + if (list.SelectedItems.Count > 1) + { + var selected = new List(); + var canCherryPick = true; + foreach (var item in list.SelectedItems) + { + if (item is Models.Commit c) + { + selected.Add(c); + + if (c.IsMerged || c.Parents.Count > 1) + canCherryPick = false; + } + } + + var multipleMenu = new ContextMenu(); + + if (canCherryPick) + { + var cherryPickMultiple = new MenuItem(); + cherryPickMultiple.Header = App.Text("CommitCM.CherryPickMultiple"); + cherryPickMultiple.Icon = App.CreateMenuIcon("Icons.CherryPick"); + cherryPickMultiple.Click += (_, e) => + { + if (PopupHost.CanCreatePopup()) + PopupHost.ShowPopup(new CherryPick(_repo, selected)); + e.Handled = true; + }; + multipleMenu.Items.Add(cherryPickMultiple); + multipleMenu.Items.Add(new MenuItem() { Header = "-" }); + } + + var copyMultipleSHAs = new MenuItem(); + copyMultipleSHAs.Header = App.Text("CommitCM.CopySHA"); + copyMultipleSHAs.Icon = App.CreateMenuIcon("Icons.Copy"); + copyMultipleSHAs.Click += (_, e) => + { + var builder = new StringBuilder(); + foreach (var c in selected) + builder.AppendLine(c.SHA); + + App.CopyText(builder.ToString()); + e.Handled = true; + }; + multipleMenu.Items.Add(copyMultipleSHAs); + + var copyMultipleInfo = new MenuItem(); + copyMultipleInfo.Header = App.Text("CommitCM.CopyInfo"); + copyMultipleInfo.Icon = App.CreateMenuIcon("Icons.Copy"); + copyMultipleInfo.Click += (_, e) => + { + var builder = new StringBuilder(); + foreach (var c in selected) + builder.AppendLine($"{c.SHA.Substring(0, 10)} - {c.Subject}"); + + App.CopyText(builder.ToString()); + e.Handled = true; + }; + multipleMenu.Items.Add(copyMultipleInfo); + + return multipleMenu; + } + var commit = (list.SelectedItem as Models.Commit)!; var menu = new ContextMenu(); var tags = new List(); @@ -324,7 +384,7 @@ namespace SourceGit.ViewModels cherryPick.Click += (_, e) => { if (PopupHost.CanCreatePopup()) - PopupHost.ShowPopup(new CherryPick(_repo, commit)); + PopupHost.ShowPopup(new CherryPick(_repo, [commit])); e.Handled = true; }; menu.Items.Add(cherryPick); diff --git a/src/Views/CherryPick.axaml b/src/Views/CherryPick.axaml index e3634bd2..ba672b13 100644 --- a/src/Views/CherryPick.axaml +++ b/src/Views/CherryPick.axaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:m="using:SourceGit.Models" xmlns:vm="using:SourceGit.ViewModels" xmlns:c="using:SourceGit.Converters" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" @@ -11,17 +12,51 @@ - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + 0 } } list) { var menu = histories.MakeContextMenu(list); list.OpenContextMenu(menu);