Skip to content

Commit f545eea

Browse files
committed
feature: add Reset File(s) to <revision> context menu entry to selected change(s) in compare view (#2079)
Signed-off-by: leo <longshuang@msn.cn>
1 parent 741a732 commit f545eea

File tree

5 files changed

+186
-11
lines changed

5 files changed

+186
-11
lines changed

src/ViewModels/Compare.cs

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Threading.Tasks;
45
using Avalonia.Threading;
56
using CommunityToolkit.Mvvm.ComponentModel;
@@ -14,6 +15,11 @@ public bool IsLoading
1415
private set => SetProperty(ref _isLoading, value);
1516
}
1617

18+
public bool CanResetFiles
19+
{
20+
get => _canResetFiles;
21+
}
22+
1723
public string BaseName
1824
{
1925
get => _baseName;
@@ -81,9 +87,10 @@ public DiffContext DiffContext
8187
private set => SetProperty(ref _diffContext, value);
8288
}
8389

84-
public Compare(string repo, object based, object to)
90+
public Compare(Repository repo, object based, object to)
8591
{
86-
_repo = repo;
92+
_repo = repo.FullPath;
93+
_canResetFiles = !repo.IsBare;
8794
_based = GetSHA(based);
8895
_to = GetSHA(to);
8996
_baseName = GetName(based);
@@ -134,6 +141,121 @@ public void OpenInExternalDiffTool(Models.Change change)
134141
new Commands.DiffTool(_repo, new Models.DiffOption(_based, _to, change)).Open();
135142
}
136143

144+
public async Task ResetToLeftAsync(Models.Change change)
145+
{
146+
if (!_canResetFiles)
147+
return;
148+
149+
if (change.Index == Models.ChangeState.Added)
150+
{
151+
var fullpath = Native.OS.GetAbsPath(_repo, change.Path);
152+
if (File.Exists(fullpath))
153+
await new Commands.Remove(_repo, [change.Path]).ExecAsync();
154+
}
155+
else if (change.Index == Models.ChangeState.Renamed)
156+
{
157+
var renamed = Native.OS.GetAbsPath(_repo, change.Path);
158+
if (File.Exists(renamed))
159+
await new Commands.Remove(_repo, [change.Path]).ExecAsync();
160+
161+
await new Commands.Checkout(_repo).FileWithRevisionAsync(change.OriginalPath, _baseHead.SHA);
162+
}
163+
else
164+
{
165+
await new Commands.Checkout(_repo).FileWithRevisionAsync(change.Path, _baseHead.SHA);
166+
}
167+
}
168+
169+
public async Task ResetToRightAsync(Models.Change change)
170+
{
171+
if (change.Index == Models.ChangeState.Deleted)
172+
{
173+
var fullpath = Native.OS.GetAbsPath(_repo, change.Path);
174+
if (File.Exists(fullpath))
175+
await new Commands.Remove(_repo, [change.Path]).ExecAsync();
176+
}
177+
else if (change.Index == Models.ChangeState.Renamed)
178+
{
179+
var old = Native.OS.GetAbsPath(_repo, change.OriginalPath);
180+
if (File.Exists(old))
181+
await new Commands.Remove(_repo, [change.OriginalPath]).ExecAsync();
182+
183+
await new Commands.Checkout(_repo).FileWithRevisionAsync(change.Path, ToHead.SHA);
184+
}
185+
else
186+
{
187+
await new Commands.Checkout(_repo).FileWithRevisionAsync(change.Path, ToHead.SHA);
188+
}
189+
}
190+
191+
public async Task ResetMultipleToLeftAsync(List<Models.Change> changes)
192+
{
193+
var checkouts = new List<string>();
194+
var removes = new List<string>();
195+
196+
foreach (var c in changes)
197+
{
198+
if (c.Index == Models.ChangeState.Added)
199+
{
200+
var fullpath = Native.OS.GetAbsPath(_repo, c.Path);
201+
if (File.Exists(fullpath))
202+
removes.Add(c.Path);
203+
}
204+
else if (c.Index == Models.ChangeState.Renamed)
205+
{
206+
var old = Native.OS.GetAbsPath(_repo, c.Path);
207+
if (File.Exists(old))
208+
removes.Add(c.Path);
209+
210+
checkouts.Add(c.OriginalPath);
211+
}
212+
else
213+
{
214+
checkouts.Add(c.Path);
215+
}
216+
}
217+
218+
if (removes.Count > 0)
219+
await new Commands.Remove(_repo, removes).ExecAsync();
220+
221+
if (checkouts.Count > 0)
222+
await new Commands.Checkout(_repo).MultipleFilesWithRevisionAsync(checkouts, _baseHead.SHA);
223+
}
224+
225+
public async Task ResetMultipleToRightAsync(List<Models.Change> changes)
226+
{
227+
var checkouts = new List<string>();
228+
var removes = new List<string>();
229+
230+
foreach (var c in changes)
231+
{
232+
if (c.Index == Models.ChangeState.Deleted)
233+
{
234+
var fullpath = Native.OS.GetAbsPath(_repo, c.Path);
235+
if (File.Exists(fullpath))
236+
removes.Add(c.Path);
237+
}
238+
else if (c.Index == Models.ChangeState.Renamed)
239+
{
240+
var renamed = Native.OS.GetAbsPath(_repo, c.OriginalPath);
241+
if (File.Exists(renamed))
242+
removes.Add(c.OriginalPath);
243+
244+
checkouts.Add(c.Path);
245+
}
246+
else
247+
{
248+
checkouts.Add(c.Path);
249+
}
250+
}
251+
252+
if (removes.Count > 0)
253+
await new Commands.Remove(_repo, removes).ExecAsync();
254+
255+
if (checkouts.Count > 0)
256+
await new Commands.Checkout(_repo).MultipleFilesWithRevisionAsync(checkouts, _toHead.SHA);
257+
}
258+
137259
public async Task SaveChangesAsPatchAsync(List<Models.Change> changes, string saveTo)
138260
{
139261
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo, changes, _based, _to, saveTo);
@@ -241,6 +363,7 @@ private string GetSHA(object obj)
241363

242364
private string _repo;
243365
private bool _isLoading = true;
366+
private bool _canResetFiles = false;
244367
private string _based = string.Empty;
245368
private string _to = string.Empty;
246369
private string _baseName = string.Empty;

src/ViewModels/CompareCommandPalette.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void ClearFilter()
5858
public void Launch()
5959
{
6060
if (_compareTo != null)
61-
App.ShowWindow(new Compare(_repo.FullPath, _basedOn, _compareTo));
61+
App.ShowWindow(new Compare(_repo, _basedOn, _compareTo));
6262
_launcher?.CancelCommandPalette();
6363
}
6464

src/Views/BranchTree.axaml.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ private void OnTreeContextRequested(object _1, ContextRequestedEventArgs _2)
528528
compare.Icon = App.CreateMenuIcon("Icons.Compare");
529529
compare.Click += (_, ev) =>
530530
{
531-
App.ShowWindow(new ViewModels.Compare(repo.FullPath, branches[0], branches[1]));
531+
App.ShowWindow(new ViewModels.Compare(repo, branches[0], branches[1]));
532532
ev.Handled = true;
533533
};
534534
menu.Items.Add(compare);
@@ -826,7 +826,7 @@ private ContextMenu CreateContextMenuForLocalBranch(ViewModels.Repository repo,
826826
compareWithCurrent.Icon = App.CreateMenuIcon("Icons.Compare");
827827
compareWithCurrent.Click += (_, _) =>
828828
{
829-
App.ShowWindow(new ViewModels.Compare(repo.FullPath, branch, current));
829+
App.ShowWindow(new ViewModels.Compare(repo, branch, current));
830830
};
831831

832832
var compareWith = new MenuItem();
@@ -1123,7 +1123,7 @@ public ContextMenu CreateContextMenuForRemoteBranch(ViewModels.Repository repo,
11231123
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
11241124
compareWithHead.Click += (_, _) =>
11251125
{
1126-
App.ShowWindow(new ViewModels.Compare(repo.FullPath, branch, current));
1126+
App.ShowWindow(new ViewModels.Compare(repo, branch, current));
11271127
};
11281128

11291129
var compareWith = new MenuItem();

src/Views/Compare.axaml.cs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,34 @@ private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e
8282
menu.Items.Add(explore);
8383
}
8484

85+
menu.Items.Add(new MenuItem() { Header = "-" });
86+
menu.Items.Add(patch);
87+
88+
if (vm.CanResetFiles)
89+
{
90+
var resetToLeft = new MenuItem();
91+
resetToLeft.Header = App.Text("ChangeCM.ResetFileTo", vm.BaseName);
92+
resetToLeft.Icon = App.CreateMenuIcon("Icons.File.Checkout");
93+
resetToLeft.Click += async (_, ev) =>
94+
{
95+
await vm.ResetToLeftAsync(change);
96+
ev.Handled = true;
97+
};
98+
99+
var resetToRight = new MenuItem();
100+
resetToRight.Header = App.Text("ChangeCM.ResetFileTo", vm.ToName);
101+
resetToRight.Icon = App.CreateMenuIcon("Icons.File.Checkout");
102+
resetToRight.Click += async (_, ev) =>
103+
{
104+
await vm.ResetToRightAsync(change);
105+
ev.Handled = true;
106+
};
107+
108+
menu.Items.Add(new MenuItem() { Header = "-" });
109+
menu.Items.Add(resetToLeft);
110+
menu.Items.Add(resetToRight);
111+
}
112+
85113
var copyPath = new MenuItem();
86114
copyPath.Header = App.Text("CopyPath");
87115
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
@@ -102,14 +130,39 @@ private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e
102130
ev.Handled = true;
103131
};
104132

105-
menu.Items.Add(new MenuItem() { Header = "-" });
106-
menu.Items.Add(patch);
107133
menu.Items.Add(new MenuItem() { Header = "-" });
108134
menu.Items.Add(copyPath);
109135
menu.Items.Add(copyFullPath);
110136
}
111137
else
112138
{
139+
menu.Items.Add(patch);
140+
141+
if (vm.CanResetFiles)
142+
{
143+
var resetToLeft = new MenuItem();
144+
resetToLeft.Header = App.Text("ChangeCM.ResetFileTo", vm.BaseName);
145+
resetToLeft.Icon = App.CreateMenuIcon("Icons.File.Checkout");
146+
resetToLeft.Click += async (_, ev) =>
147+
{
148+
await vm.ResetMultipleToLeftAsync(selected);
149+
ev.Handled = true;
150+
};
151+
152+
var resetToRight = new MenuItem();
153+
resetToRight.Header = App.Text("ChangeCM.ResetFileTo", vm.ToName);
154+
resetToRight.Icon = App.CreateMenuIcon("Icons.File.Checkout");
155+
resetToRight.Click += async (_, ev) =>
156+
{
157+
await vm.ResetMultipleToRightAsync(selected);
158+
ev.Handled = true;
159+
};
160+
161+
menu.Items.Add(new MenuItem() { Header = "-" });
162+
menu.Items.Add(resetToLeft);
163+
menu.Items.Add(resetToRight);
164+
}
165+
113166
var copyPath = new MenuItem();
114167
copyPath.Header = App.Text("CopyPath");
115168
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
@@ -138,7 +191,6 @@ private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e
138191
ev.Handled = true;
139192
};
140193

141-
menu.Items.Add(patch);
142194
menu.Items.Add(new MenuItem() { Header = "-" });
143195
menu.Items.Add(copyPath);
144196
menu.Items.Add(copyFullPath);

src/Views/TagsView.axaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ private void OnTagsContextMenuRequested(object sender, ContextRequestedEventArgs
262262
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
263263
compareWithHead.Click += (_, _) =>
264264
{
265-
App.ShowWindow(new ViewModels.Compare(repo.FullPath, tag, repo.CurrentBranch));
265+
App.ShowWindow(new ViewModels.Compare(repo, tag, repo.CurrentBranch));
266266
};
267267

268268
var compareWith = new MenuItem();
@@ -380,7 +380,7 @@ private void OnTagsContextMenuRequested(object sender, ContextRequestedEventArgs
380380
if (based.CreatorDate > to.CreatorDate)
381381
(based, to) = (to, based);
382382

383-
App.ShowWindow(new ViewModels.Compare(repo.FullPath, based, to));
383+
App.ShowWindow(new ViewModels.Compare(repo, based, to));
384384
ev.Handled = true;
385385
};
386386
menu.Items.Add(compare);

0 commit comments

Comments
 (0)