Skip to content

Commit 96a9e99

Browse files
love-lingerybeapps
andcommitted
feature: add Reset File(s) to <revision> context menu entry to selected change(s) in revision compare view (#2079)
Co-authored-by: ybeapps <ybeapps@gmail.com> Signed-off-by: leo <longshuang@msn.cn>
1 parent 769c220 commit 96a9e99

File tree

6 files changed

+248
-25
lines changed

6 files changed

+248
-25
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">Generate commit message</x:String>
9696
<x:String x:Key="Text.ChangeCM.Merge" xml:space="preserve">Merge (Built-in)</x:String>
9797
<x:String x:Key="Text.ChangeCM.MergeExternal" xml:space="preserve">Merge (External)</x:String>
98+
<x:String x:Key="Text.ChangeCM.ResetFileTo" xml:space="preserve">Reset File(s) to ${0}$</x:String>
9899
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGE DISPLAY MODE</x:String>
99100
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Show as File and Dir List</x:String>
100101
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Show as Path List</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">生成提交信息</x:String>
100100
<x:String x:Key="Text.ChangeCM.Merge" xml:space="preserve">解决冲突(内部工具)</x:String>
101101
<x:String x:Key="Text.ChangeCM.MergeExternal" xml:space="preserve">解决冲突(外部工具)</x:String>
102+
<x:String x:Key="Text.ChangeCM.ResetFileTo" xml:space="preserve">重置文件到 ${0}$</x:String>
102103
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切换变更显示模式</x:String>
103104
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">文件名+路径列表模式</x:String>
104105
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路径列表模式</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">產生提交訊息</x:String>
100100
<x:String x:Key="Text.ChangeCM.Merge" xml:space="preserve">解決衝突 (內建工具)</x:String>
101101
<x:String x:Key="Text.ChangeCM.MergeExternal" xml:space="preserve">解決衝突 (外部工具)</x:String>
102+
<x:String x:Key="Text.ChangeCM.ResetFileTo" xml:space="preserve">重設檔案到 ${0}$</x:String>
102103
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切換變更顯示模式</x:String>
103104
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">檔案名稱 + 路徑列表模式</x:String>
104105
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路徑列表模式</x:String>

src/ViewModels/Histories.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public void Select(IList commits)
206206

207207
var end = commits[0] as Models.Commit;
208208
var start = commits[1] as Models.Commit;
209-
DetailContext = new RevisionCompare(_repo.FullPath, start, end);
209+
DetailContext = new RevisionCompare(_repo, start, end);
210210
}
211211
else
212212
{
@@ -403,7 +403,7 @@ public async Task<string> GetCommitFullMessageAsync(Models.Commit commit)
403403
_repo.SearchCommitContext.Selected = null;
404404
head = await new Commands.QuerySingleCommit(_repo.FullPath, "HEAD").GetResultAsync();
405405
if (head != null)
406-
DetailContext = new RevisionCompare(_repo.FullPath, commit, head);
406+
DetailContext = new RevisionCompare(_repo, commit, head);
407407

408408
return null;
409409
}
@@ -413,7 +413,7 @@ public async Task<string> GetCommitFullMessageAsync(Models.Commit commit)
413413

414414
public void CompareWithWorktree(Models.Commit commit)
415415
{
416-
DetailContext = new RevisionCompare(_repo.FullPath, commit, null);
416+
DetailContext = new RevisionCompare(_repo, commit, null);
417417
}
418418

419419
private Repository _repo = null;

src/ViewModels/RevisionCompare.cs

Lines changed: 196 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Threading.Tasks;
5+
46
using Avalonia.Threading;
57
using CommunityToolkit.Mvvm.ComponentModel;
68

@@ -26,7 +28,30 @@ public object EndPoint
2628
private set => SetProperty(ref _endPoint, value);
2729
}
2830

29-
public bool CanSaveAsPatch { get; }
31+
public string LeftSideDesc
32+
{
33+
get => GetDesc(StartPoint);
34+
}
35+
36+
public string RightSideDesc
37+
{
38+
get => GetDesc(EndPoint);
39+
}
40+
41+
public bool CanResetToLeft
42+
{
43+
get => !_repo.IsBare && _startPoint != null;
44+
}
45+
46+
public bool CanResetToRight
47+
{
48+
get => !_repo.IsBare && _endPoint != null;
49+
}
50+
51+
public bool CanSaveAsPatch
52+
{
53+
get => _startPoint != null && _endPoint != null;
54+
}
3055

3156
public int TotalChanges
3257
{
@@ -50,7 +75,7 @@ public List<Models.Change> SelectedChanges
5075
if (value is { Count: 1 })
5176
{
5277
var option = new Models.DiffOption(GetSHA(_startPoint), GetSHA(_endPoint), value[0]);
53-
DiffContext = new DiffContext(_repo, option, _diffContext);
78+
DiffContext = new DiffContext(_repo.FullPath, option, _diffContext);
5479
}
5580
else
5681
{
@@ -76,12 +101,11 @@ public DiffContext DiffContext
76101
private set => SetProperty(ref _diffContext, value);
77102
}
78103

79-
public RevisionCompare(string repo, Models.Commit startPoint, Models.Commit endPoint)
104+
public RevisionCompare(Repository repo, Models.Commit startPoint, Models.Commit endPoint)
80105
{
81106
_repo = repo;
82107
_startPoint = (object)startPoint ?? new Models.Null();
83108
_endPoint = (object)endPoint ?? new Models.Null();
84-
CanSaveAsPatch = startPoint != null && endPoint != null;
85109
Refresh();
86110
}
87111

@@ -100,23 +124,12 @@ public void Dispose()
100124
public void OpenChangeWithExternalDiffTool(Models.Change change)
101125
{
102126
var opt = new Models.DiffOption(GetSHA(_startPoint), GetSHA(_endPoint), change);
103-
new Commands.DiffTool(_repo, opt).Open();
127+
new Commands.DiffTool(_repo.FullPath, opt).Open();
104128
}
105129

106130
public void NavigateTo(string commitSHA)
107131
{
108-
var launcher = App.GetLauncher();
109-
if (launcher == null)
110-
return;
111-
112-
foreach (var page in launcher.Pages)
113-
{
114-
if (page.Data is Repository repo && repo.FullPath.Equals(_repo))
115-
{
116-
repo.NavigateToCommit(commitSHA);
117-
break;
118-
}
119-
}
132+
_repo?.NavigateToCommit(commitSHA);
120133
}
121134

122135
public void Swap()
@@ -130,14 +143,170 @@ public void Swap()
130143

131144
public string GetAbsPath(string path)
132145
{
133-
return Native.OS.GetAbsPath(_repo, path);
146+
return Native.OS.GetAbsPath(_repo.FullPath, path);
147+
}
148+
149+
public async Task ResetToLeftAsync(Models.Change change)
150+
{
151+
var sha = GetSHA(_startPoint);
152+
var log = _repo.CreateLog($"Reset File to '{GetDesc(_startPoint)}'");
153+
154+
if (change.Index == Models.ChangeState.Added)
155+
{
156+
var fullpath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
157+
if (File.Exists(fullpath))
158+
await new Commands.Remove(_repo.FullPath, [change.Path])
159+
.Use(log)
160+
.ExecAsync();
161+
}
162+
else if (change.Index == Models.ChangeState.Renamed)
163+
{
164+
var renamed = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
165+
if (File.Exists(renamed))
166+
await new Commands.Remove(_repo.FullPath, [change.Path])
167+
.Use(log)
168+
.ExecAsync();
169+
170+
await new Commands.Checkout(_repo.FullPath)
171+
.Use(log)
172+
.FileWithRevisionAsync(change.OriginalPath, sha);
173+
}
174+
else
175+
{
176+
await new Commands.Checkout(_repo.FullPath)
177+
.Use(log)
178+
.FileWithRevisionAsync(change.Path, sha);
179+
}
180+
181+
log.Complete();
182+
}
183+
184+
public async Task ResetToRightAsync(Models.Change change)
185+
{
186+
var sha = GetSHA(_endPoint);
187+
var log = _repo.CreateLog($"Reset File to '{GetDesc(_endPoint)}'");
188+
189+
if (change.Index == Models.ChangeState.Deleted)
190+
{
191+
var fullpath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
192+
if (File.Exists(fullpath))
193+
await new Commands.Remove(_repo.FullPath, [change.Path])
194+
.Use(log)
195+
.ExecAsync();
196+
}
197+
else if (change.Index == Models.ChangeState.Renamed)
198+
{
199+
var old = Native.OS.GetAbsPath(_repo.FullPath, change.OriginalPath);
200+
if (File.Exists(old))
201+
await new Commands.Remove(_repo.FullPath, [change.OriginalPath])
202+
.Use(log)
203+
.ExecAsync();
204+
205+
await new Commands.Checkout(_repo.FullPath)
206+
.Use(log)
207+
.FileWithRevisionAsync(change.Path, sha);
208+
}
209+
else
210+
{
211+
await new Commands.Checkout(_repo.FullPath)
212+
.Use(log)
213+
.FileWithRevisionAsync(change.Path, sha);
214+
}
215+
216+
log.Complete();
217+
}
218+
219+
public async Task ResetMultipleToLeftAsync(List<Models.Change> changes)
220+
{
221+
var sha = GetSHA(_startPoint);
222+
var checkouts = new List<string>();
223+
var removes = new List<string>();
224+
225+
foreach (var c in changes)
226+
{
227+
if (c.Index == Models.ChangeState.Added)
228+
{
229+
var fullpath = Native.OS.GetAbsPath(_repo.FullPath, c.Path);
230+
if (File.Exists(fullpath))
231+
removes.Add(c.Path);
232+
}
233+
else if (c.Index == Models.ChangeState.Renamed)
234+
{
235+
var old = Native.OS.GetAbsPath(_repo.FullPath, c.Path);
236+
if (File.Exists(old))
237+
removes.Add(c.Path);
238+
239+
checkouts.Add(c.OriginalPath);
240+
}
241+
else
242+
{
243+
checkouts.Add(c.Path);
244+
}
245+
}
246+
247+
var log = _repo.CreateLog($"Reset Files to '{GetDesc(_startPoint)}'");
248+
249+
if (removes.Count > 0)
250+
await new Commands.Remove(_repo.FullPath, removes)
251+
.Use(log)
252+
.ExecAsync();
253+
254+
if (checkouts.Count > 0)
255+
await new Commands.Checkout(_repo.FullPath)
256+
.Use(log)
257+
.MultipleFilesWithRevisionAsync(checkouts, sha);
258+
259+
log.Complete();
260+
}
261+
262+
public async Task ResetMultipleToRightAsync(List<Models.Change> changes)
263+
{
264+
var sha = GetSHA(_endPoint);
265+
var checkouts = new List<string>();
266+
var removes = new List<string>();
267+
268+
foreach (var c in changes)
269+
{
270+
if (c.Index == Models.ChangeState.Deleted)
271+
{
272+
var fullpath = Native.OS.GetAbsPath(_repo.FullPath, c.Path);
273+
if (File.Exists(fullpath))
274+
removes.Add(c.Path);
275+
}
276+
else if (c.Index == Models.ChangeState.Renamed)
277+
{
278+
var renamed = Native.OS.GetAbsPath(_repo.FullPath, c.OriginalPath);
279+
if (File.Exists(renamed))
280+
removes.Add(c.OriginalPath);
281+
282+
checkouts.Add(c.Path);
283+
}
284+
else
285+
{
286+
checkouts.Add(c.Path);
287+
}
288+
}
289+
290+
var log = _repo.CreateLog($"Reset Files to '{GetDesc(_endPoint)}'");
291+
292+
if (removes.Count > 0)
293+
await new Commands.Remove(_repo.FullPath, removes)
294+
.Use(log)
295+
.ExecAsync();
296+
297+
if (checkouts.Count > 0)
298+
await new Commands.Checkout(_repo.FullPath)
299+
.Use(log)
300+
.MultipleFilesWithRevisionAsync(checkouts, sha);
301+
302+
log.Complete();
134303
}
135304

136305
public async Task SaveChangesAsPatchAsync(List<Models.Change> changes, string saveTo)
137306
{
138-
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo, changes ?? _changes, GetSHA(_startPoint), GetSHA(_endPoint), saveTo);
307+
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, changes ?? _changes, GetSHA(_startPoint), GetSHA(_endPoint), saveTo);
139308
if (succ)
140-
App.SendNotification(_repo, App.Text("SaveAsPatchSuccess"));
309+
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
141310
}
142311

143312
public void ClearSearchFilter()
@@ -171,7 +340,7 @@ private void Refresh()
171340
{
172341
Task.Run(async () =>
173342
{
174-
_changes = await new Commands.CompareRevisions(_repo, GetSHA(_startPoint), GetSHA(_endPoint))
343+
_changes = await new Commands.CompareRevisions(_repo.FullPath, GetSHA(_startPoint), GetSHA(_endPoint))
175344
.ReadAsync()
176345
.ConfigureAwait(false);
177346

@@ -205,7 +374,12 @@ private string GetSHA(object obj)
205374
return obj is Models.Commit commit ? commit.SHA : string.Empty;
206375
}
207376

208-
private string _repo;
377+
private string GetDesc(object obj)
378+
{
379+
return obj is Models.Commit commit ? commit.GetFriendlyName() : App.Text("Worktree");
380+
}
381+
382+
private Repository _repo;
209383
private bool _isLoading = true;
210384
private object _startPoint = null;
211385
private object _endPoint = null;

0 commit comments

Comments
 (0)