Skip to content

Commit f29fb16

Browse files
committed
stop search
1 parent 24607ae commit f29fb16

File tree

16 files changed

+653
-210
lines changed

16 files changed

+653
-210
lines changed

GitContentSearch.Tests/GitFileLocatorTests.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using GitContentSearch.Interfaces;
22
using Moq;
3+
using System.Threading;
34

45
namespace GitContentSearch.Tests
56
{
@@ -42,7 +43,8 @@ public void LocateFile_FileNotFound_ReturnsNull()
4243
_mockProcessWrapper.Setup(x => x.StartAndProcessOutput(
4344
It.Is<string>(cmd => cmd == "log --all --pretty=format:%H"),
4445
It.IsAny<string>(),
45-
It.IsAny<Action<string>>()
46+
It.IsAny<Action<string>>(),
47+
It.IsAny<CancellationToken>()
4648
));
4749

4850
// Act
@@ -80,8 +82,9 @@ public void LocateFile_FileFound_ReturnsLatestCommit()
8082
.Setup(x => x.StartAndProcessOutput(
8183
It.Is<string>(cmd => cmd == "log --all --pretty=format:%H"),
8284
It.IsAny<string>(),
83-
It.IsAny<Action<string>>()))
84-
.Callback((string cmd, string dir, Action<string> callback) =>
85+
It.IsAny<Action<string>>(),
86+
It.IsAny<CancellationToken>()))
87+
.Callback((string cmd, string dir, Action<string> callback, CancellationToken token) =>
8588
{
8689
callback(fullCommitHash);
8790
processOutputCalled = true;
@@ -91,8 +94,9 @@ public void LocateFile_FileFound_ReturnsLatestCommit()
9194
.Setup(x => x.StartAndProcessOutput(
9295
It.Is<string>(cmd => cmd == $"ls-tree --name-only -r {fullCommitHash}"),
9396
It.IsAny<string>(),
94-
It.IsAny<Action<string>>()))
95-
.Callback((string cmd, string dir, Action<string> callback) =>
97+
It.IsAny<Action<string>>(),
98+
It.IsAny<CancellationToken>()))
99+
.Callback((string cmd, string dir, Action<string> callback, CancellationToken token) =>
96100
{
97101
callback(expectedFilePath);
98102
});
@@ -101,7 +105,8 @@ public void LocateFile_FileFound_ReturnsLatestCommit()
101105
.Setup(x => x.StartAndProcessOutput(
102106
It.Is<string>(cmd => cmd == $"log --follow --name-status {fullCommitHash}..HEAD"),
103107
It.IsAny<string>(),
104-
It.IsAny<Action<string>>()));
108+
It.IsAny<Action<string>>(),
109+
It.IsAny<CancellationToken>()));
105110

106111
// Act
107112
var result = _gitLocator.LocateFile(searchFileName);

GitContentSearch.Tests/GitHelperTests.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using Xunit;
66
using LibGit2Sharp;
7+
using System.Threading;
78

89
namespace GitContentSearch.Tests
910
{
@@ -29,6 +30,8 @@ public void GetGitCommits_ShouldReturnEmptyList_OnGitFailure()
2930

3031
var processResult = new ProcessResult(string.Empty, "Error occurred", 1);
3132
processWrapperMock.Setup(pw => pw.Start(It.IsAny<ProcessStartInfo>(), null)).Returns(processResult);
33+
processWrapperMock.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
34+
.Returns(processResult);
3235

3336
var gitHelper = new GitHelper(processWrapperMock.Object);
3437

@@ -77,7 +80,8 @@ public void GetGitCommits_ShouldReturnCorrectRange_WhenBothCommitsArePresent()
7780

7881
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
7982
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
80-
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), null, null)).Returns(processResult);
83+
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
84+
.Returns(processResult);
8185

8286
var gitHelper = new GitHelper(processWrapperMock.Object);
8387

@@ -103,7 +107,8 @@ public void GetGitCommits_ShouldReturnFullRange_WhenEarliestAndLatestAreEmpty()
103107

104108
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
105109
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
106-
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), null, null)).Returns(processResult);
110+
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
111+
.Returns(processResult);
107112

108113
var gitHelper = new GitHelper(processWrapperMock.Object);
109114

@@ -131,7 +136,8 @@ public void GetGitCommits_ShouldReturnPartialRange_WhenOnlyEarliestCommitIsSpeci
131136

132137
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
133138
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
134-
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), null, null)).Returns(processResult);
139+
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
140+
.Returns(processResult);
135141

136142
var gitHelper = new GitHelper(processWrapperMock.Object);
137143

@@ -157,7 +163,8 @@ public void GetGitCommits_ShouldReturnPartialRange_WhenOnlyLatestCommitIsSpecifi
157163

158164
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
159165
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
160-
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), null, null)).Returns(processResult);
166+
processWrapperMock.Setup(pw => pw.Start(It.Is<string>(x => x.Trim() == "log --pretty=format:%H"), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
167+
.Returns(processResult);
161168

162169
var gitHelper = new GitHelper(processWrapperMock.Object);
163170

@@ -183,7 +190,8 @@ public void GetGitCommits_ShouldReturnEmptyList_WhenCommitsAreInWrongOrder()
183190

184191
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
185192
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
186-
processWrapperMock.Setup(pw => pw.Start(It.IsAny<ProcessStartInfo>(), null)).Returns(processResult);
193+
processWrapperMock.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
194+
.Returns(processResult);
187195

188196
var gitHelper = new GitHelper(processWrapperMock.Object);
189197

@@ -202,7 +210,8 @@ public void GetGitCommits_ShouldReturnEmptyList_WhenEarliestCommitIsNotFound()
202210

203211
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
204212
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
205-
processWrapperMock.Setup(pw => pw.Start(It.IsAny<ProcessStartInfo>(), null)).Returns(processResult);
213+
processWrapperMock.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
214+
.Returns(processResult);
206215

207216
var gitHelper = new GitHelper(processWrapperMock.Object);
208217

@@ -221,7 +230,8 @@ public void GetGitCommits_ShouldReturnEmptyList_WhenLatestCommitIsNotFound()
221230

222231
var gitLogOutput = "commit5\ncommit4\ncommit3\ncommit2\ncommit1";
223232
var processResult = new ProcessResult(gitLogOutput, string.Empty, 0);
224-
processWrapperMock.Setup(pw => pw.Start(It.IsAny<ProcessStartInfo>(), null)).Returns(processResult);
233+
processWrapperMock.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
234+
.Returns(processResult);
225235

226236
var gitHelper = new GitHelper(processWrapperMock.Object);
227237

@@ -254,8 +264,8 @@ public void GetCommits_ShouldFormatFilePath_Correctly(string inputPath, string e
254264
// Setup mock to capture the actual command
255265
string? capturedCommand = null;
256266
processWrapperMock
257-
.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>()))
258-
.Callback<string, string?, Stream?>((cmd, dir, stream) => capturedCommand = cmd)
267+
.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
268+
.Callback<string, string?, Stream?, CancellationToken>((cmd, dir, stream, token) => capturedCommand = cmd)
259269
.Returns(new ProcessResult(string.Empty, string.Empty, 0));
260270

261271
// Act
@@ -278,8 +288,8 @@ public void GetCommitsWithFollow_ShouldFormatFilePath_Correctly(string inputPath
278288
// Setup mock to capture the actual command
279289
string? capturedCommand = null;
280290
processWrapperMock
281-
.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>()))
282-
.Callback<string, string?, Stream?>((cmd, dir, stream) => capturedCommand = cmd)
291+
.Setup(pw => pw.Start(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
292+
.Callback<string, string?, Stream?, CancellationToken>((cmd, dir, stream, token) => capturedCommand = cmd)
283293
.Returns(new ProcessResult(string.Empty, string.Empty, 0));
284294

285295
// Act

GitContentSearch.UI/App.axaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@
4242
<Setter Property="RenderTransform" Value="scale(0.98)"/>
4343
</Style>
4444

45+
<!-- Stop Button Style (for stopping search) -->
46+
<Style Selector="Button.Stop">
47+
<Setter Property="Background" Value="#E65100"/>
48+
<Setter Property="Foreground" Value="White"/>
49+
<Setter Property="BorderThickness" Value="0"/>
50+
</Style>
51+
52+
<Style Selector="Button.Stop:pointerover /template/ ContentPresenter">
53+
<Setter Property="Background" Value="#F57C00"/>
54+
<Setter Property="Foreground" Value="White"/>
55+
</Style>
56+
57+
<Style Selector="Button.Stop:pressed /template/ ContentPresenter">
58+
<Setter Property="Background" Value="#EF6C00"/>
59+
<Setter Property="Foreground" Value="White"/>
60+
<Setter Property="RenderTransform" Value="scale(0.98)"/>
61+
</Style>
62+
63+
<Style Selector="Button.Stop:disabled /template/ ContentPresenter">
64+
<Setter Property="Background" Value="#E65100"/>
65+
<Setter Property="Foreground" Value="White"/>
66+
<Setter Property="Opacity" Value="1"/>
67+
</Style>
68+
4569
<!-- Secondary Button Style (for actions like Browse) -->
4670
<Style Selector="Button.Secondary">
4771
<Setter Property="Background" Value="Transparent"/>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Avalonia.Data.Converters;
2+
using System;
3+
using System.Globalization;
4+
5+
namespace GitContentSearch.UI.Converters;
6+
7+
public class BoolConverter : IValueConverter
8+
{
9+
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
10+
{
11+
if (value is bool isTrue && parameter is string text)
12+
{
13+
return isTrue ? text : "Start Search";
14+
}
15+
return "Start Search";
16+
}
17+
18+
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
19+
{
20+
throw new NotImplementedException();
21+
}
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Avalonia.Data.Converters;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Globalization;
5+
6+
namespace GitContentSearch.UI.Converters;
7+
8+
public class OperationButtonTextConverter : IMultiValueConverter
9+
{
10+
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
11+
{
12+
if (values.Count >= 2 && values[0] is bool isSearching && values[1] is bool isLocateOperation)
13+
{
14+
if (!isSearching)
15+
{
16+
return "Start Search";
17+
}
18+
else
19+
{
20+
return isLocateOperation ? "Stop Locate" : "Stop Search";
21+
}
22+
}
23+
24+
return "Start Search";
25+
}
26+
}

0 commit comments

Comments
 (0)