Skip to content

Commit 7fa1414

Browse files
committed
refactor(cli): Decouple console output; add CommandCompleted event
Refactor fastboot output handling so the driver no longer writes directly to Console. Add FastbootCommandEventArgs and a CommandCompleted event with NotifyCommandCompleted, remove default printing in NotifyCurrentStep/NotifyProgress, and route RawCommand completion through the new notifier. Expose FastbootDebug.Output delegate (CLI sets it to write to stderr) and update Program.cs to subscribe to events and perform all console formatting/printing there. Adjusted InternalDownloadDataBytes to return the raw response on protocol mismatch and replaced direct debug writes with FastbootDebug.Log. Updated tests to expect no default console output for progress/current-step.
1 parent 892c84e commit 7fa1414

File tree

7 files changed

+82
-72
lines changed

7 files changed

+82
-72
lines changed

FastbootCLI/Program.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Program
1616
static void Main(string[] args)
1717
{
1818
FastbootDebug.IsEnabled = Environment.GetEnvironmentVariable("FASTBOOT_DEBUG") == "1";
19+
FastbootDebug.Output = message => Console.Error.WriteLine($"[DEBUG] {message}");
1920

2021
if (args.Length == 0) { ShowHelp(); return; }
2122

@@ -43,7 +44,7 @@ static void Main(string[] args)
4344
}
4445
else if (arg == "--debug") FastbootDebug.IsEnabled = true;
4546
else if (arg == "--fallback") UsbManager.ForceLibUsb = false;
46-
else if (arg == "--version" || arg == "version") { Console.WriteLine("fastboot version 1.2.5"); return; }
47+
else if (arg == "--version" || arg == "version") { Console.Error.WriteLine("fastboot version 1.2.5"); return; }
4748
else if (arg == "-h" || arg == "--help" || arg == "help") { ShowHelp(); return; }
4849
else if (!arg.StartsWith("-"))
4950
{
@@ -107,6 +108,56 @@ static void Main(string[] args)
107108
util.ReceivedFromDevice += (s, e) =>
108109
{
109110
if (e.NewInfo != null) Console.Error.WriteLine("(bootloader) " + e.NewInfo);
111+
if (e.NewText != null) Console.Error.Write(e.NewText);
112+
};
113+
util.CommandCompleted += (s, e) =>
114+
{
115+
if (e.Quiet) return;
116+
117+
var command = e.Command;
118+
var response = e.Response;
119+
if (response.Result == FastbootState.Fail)
120+
{
121+
if (command.StartsWith("snapshot-update", StringComparison.OrdinalIgnoreCase))
122+
{
123+
Console.Error.WriteLine($"Snapshot FAILED (remote: '{response.Response}')");
124+
}
125+
else if (!command.StartsWith("getvar:", StringComparison.OrdinalIgnoreCase))
126+
{
127+
Console.Error.WriteLine($"FAILED (remote: '{response.Response}')");
128+
}
129+
return;
130+
}
131+
132+
if (command.StartsWith("devices", StringComparison.OrdinalIgnoreCase))
133+
{
134+
if (!string.IsNullOrEmpty(response.Response))
135+
{
136+
Console.WriteLine(response.Response);
137+
}
138+
return;
139+
}
140+
141+
if (string.IsNullOrEmpty(response.Response)) return;
142+
143+
if (command.StartsWith("getvar:", StringComparison.OrdinalIgnoreCase) &&
144+
!string.Equals(command, "getvar:all", StringComparison.OrdinalIgnoreCase))
145+
{
146+
string key = command.Substring("getvar:".Length);
147+
bool alreadyPrinted = response.Info.Any(i => i.StartsWith(key + ":", StringComparison.OrdinalIgnoreCase));
148+
if (!alreadyPrinted)
149+
{
150+
Console.Error.WriteLine($"{key}: {response.Response}");
151+
}
152+
}
153+
else if (!command.StartsWith("getvar:all", StringComparison.OrdinalIgnoreCase))
154+
{
155+
Console.Error.WriteLine(response.Response);
156+
}
157+
};
158+
util.CurrentStepChanged += (s, step) =>
159+
{
160+
if (!string.IsNullOrEmpty(step)) Console.Error.WriteLine(step);
110161
};
111162

112163
foreach (var cmd in pendingCommands)

FirmwareKit.Comm.Fastboot.Tests/FastbootProtocolTests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ public void FlashUnsparseImage_ExactLimit_CompressesIfNeeded()
763763
}
764764

765765
[Fact]
766-
public void NotifyCurrentStep_DefaultWritesToConsole()
766+
public void NotifyCurrentStep_DefaultDoesNotWriteToConsole()
767767
{
768768
var util = new FastbootDriver(new ProtocolDownloadCaptureTransport());
769769
using var err = new StringWriter();
@@ -773,11 +773,11 @@ public void NotifyCurrentStep_DefaultWritesToConsole()
773773
Console.SetError(orig);
774774

775775
string output = err.ToString();
776-
Assert.Contains("example step", output);
776+
Assert.Equal(string.Empty, output);
777777
}
778778

779779
[Fact]
780-
public void NotifyProgress_DefaultWritesToConsole()
780+
public void NotifyProgress_DefaultDoesNotWriteToConsole()
781781
{
782782
var util = new FastbootDriver(new ProtocolDownloadCaptureTransport());
783783
using var err = new StringWriter();
@@ -787,8 +787,7 @@ public void NotifyProgress_DefaultWritesToConsole()
787787
Console.SetError(orig);
788788

789789
string output = err.ToString();
790-
Assert.Contains("50/200", output);
791-
Assert.Contains("25%", output);
790+
Assert.Equal(string.Empty, output);
792791
}
793792

794793
[Fact]

FirmwareKit.Comm.Fastboot/Command/InternalDownloadDataBytes.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ public FastbootResponse DownloadData(byte[] data)
2323
FastbootResponse response = RawCommand("download:" + data.Length.ToString("x8"));
2424
if (response.Result != FastbootState.Data)
2525
{
26-
return new FastbootResponse
27-
{
28-
Result = FastbootState.Fail,
29-
Response = "protocol error: expected DATA response to download command, got " + response.Result +
30-
(string.IsNullOrEmpty(response.Response) ? string.Empty : " (" + response.Response + ")")
31-
};
26+
return response;
3227
}
3328
if (response.DataSize != data.Length)
3429
{

FirmwareKit.Comm.Fastboot/Command/InternalRawCommand.cs

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -38,48 +38,7 @@ public FastbootResponse RawCommand(string command, bool quiet = false)
3838
FastbootDebug.Log("Waiting for response...");
3939
var response = HandleResponse();
4040
FastbootDebug.Log("Response received: " + response.Response);
41-
42-
if (quiet)
43-
{
44-
return response;
45-
}
46-
47-
if (response.Result == FastbootState.Fail)
48-
{
49-
if (command.StartsWith("snapshot-update", StringComparison.OrdinalIgnoreCase))
50-
{
51-
Console.Error.WriteLine($"Snapshot FAILED (remote: '{response.Response}')");
52-
}
53-
else if (!command.StartsWith("getvar:", StringComparison.OrdinalIgnoreCase))
54-
{
55-
Console.Error.WriteLine($"FAILED (remote: '{response.Response}')");
56-
}
57-
}
58-
else if (command.StartsWith("devices"))
59-
{
60-
Console.WriteLine(response.Response);
61-
}
62-
else if (!string.IsNullOrEmpty(response.Response))
63-
{
64-
if (command.StartsWith("getvar:", StringComparison.OrdinalIgnoreCase) &&
65-
!string.Equals(command, "getvar:all", StringComparison.OrdinalIgnoreCase))
66-
{
67-
string key = command.Substring("getvar:".Length);
68-
bool alreadyPrinted = response.Info.Any(i => i.StartsWith(key + ":", StringComparison.OrdinalIgnoreCase));
69-
if (!alreadyPrinted)
70-
{
71-
Console.Error.WriteLine($"{key}: {response.Response}");
72-
}
73-
}
74-
else if (command.StartsWith("getvar:all", StringComparison.OrdinalIgnoreCase))
75-
{
76-
// Already printed via INFO
77-
}
78-
else
79-
{
80-
Console.Error.WriteLine(response.Response);
81-
}
82-
}
41+
NotifyCommandCompleted(command, response, quiet);
8342

8443
return response;
8544
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace FirmwareKit.Comm.Fastboot;
2+
3+
public class FastbootCommandEventArgs : EventArgs
4+
{
5+
public string Command { get; }
6+
public FastbootResponse Response { get; }
7+
public bool Quiet { get; }
8+
9+
public FastbootCommandEventArgs(string command, FastbootResponse response, bool quiet)
10+
{
11+
Command = command;
12+
Response = response;
13+
Quiet = quiet;
14+
}
15+
}

FirmwareKit.Comm.Fastboot/FastbootDebug.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace FirmwareKit.Comm.Fastboot;
33
public static class FastbootDebug
44
{
55
private static bool? _debugEnabled;
6+
public static Action<string>? Output;
67

78
public static bool IsEnabled
89
{
@@ -21,7 +22,7 @@ public static void Log(string message)
2122
{
2223
if (IsEnabled)
2324
{
24-
Console.Error.WriteLine($"[DEBUG] {message}");
25+
Output?.Invoke(message);
2526
}
2627
}
2728
}

FirmwareKit.Comm.Fastboot/FastbootDriver.cs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -158,34 +158,24 @@ public static LpMetadata ReadFromImageStream(Stream stream)
158158
public event EventHandler<FastbootReceivedFromDeviceEventArgs>? ReceivedFromDevice;
159159
public event EventHandler<(long, long)>? DataTransferProgressChanged;
160160
public event EventHandler<string>? CurrentStepChanged;
161+
public event EventHandler<FastbootCommandEventArgs>? CommandCompleted;
162+
163+
internal void NotifyCommandCompleted(string command, FastbootResponse response, bool quiet)
164+
{
165+
CommandCompleted?.Invoke(this, new FastbootCommandEventArgs(command, response, quiet));
166+
}
161167

162168
public void NotifyCurrentStep(string step)
163169
{
164170
FastbootDebug.Log($"NotifyCurrentStep(step={step})");
165171

166-
// by default write progress messages similar to the AOSP fastboot tool
167-
if (string.IsNullOrEmpty(step) == false &&
168-
(CurrentStepChanged == null || CurrentStepChanged.GetInvocationList().Length == 0))
169-
{
170-
// official fastboot prints the status text directly, no prefix
171-
Console.Error.WriteLine(step);
172-
}
173-
174172
CurrentStepChanged?.Invoke(this, step);
175173
}
176174

177175
public void NotifyProgress(long current, long total)
178176
{
179177
FastbootDebug.Log($"NotifyProgress(current={current}, total={total})");
180178
DataTransferProgressChanged?.Invoke(this, (current, total));
181-
182-
// if nobody is handling progress events we still print a basic line
183-
if (DataTransferProgressChanged == null || DataTransferProgressChanged.GetInvocationList().Length == 0)
184-
{
185-
int percent = total > 0 ? (int)(current * 100 / total) : 0;
186-
Console.Error.Write($"\r{current}/{total} {percent}% ");
187-
if (current == total) Console.Error.WriteLine();
188-
}
189179
}
190180
public void NotifyReceived(FastbootState state, string? info = null, string? text = null)
191181
{
@@ -632,7 +622,7 @@ public void FlashImage(string partition, string filePath, string? slotOverride,
632622
}
633623
catch (Exception ex)
634624
{
635-
if (FastbootDebug.IsEnabled) Console.Error.WriteLine("[DEBUG] FlashImage Failed: " + ex);
625+
FastbootDebug.Log("FlashImage Failed: " + ex);
636626
throw;
637627
}
638628
}

0 commit comments

Comments
 (0)