Skip to content

Commit 9ea5864

Browse files
author
Stewart Miles
committed
Improved support for batch mode execution of resolution steps.
* Moved main thread task execution logic to the RunOnMainThread class. This simplifies the process of scheduling execution on the main thread in the Unity editor and enabled addition of support for synchronous execution when running in batch mode where UnityEditor.EditorApplication.update is not called. * CommandLine and CommandLineDialog classes will now execute all command line operations synchronously when running in batch mode. * Added logging to CommandLineDialog in batch mode and when running with verbose logging enabled. * Moved batch mode testing logic and Unity version checking to the ExceutionEnvironment class. * Moved all explicit use of EditorApplication.update to RunOnMainThread methods so tasks are executed correctly in batch mode. * Added batch mode support to CommandLineDialog (Unity crashes when showing editor windows in batch mode with no graphics). * Fixed variable replacement in AndroidManifest.xml files. Values like "${applicationId}.foo" were being replaced by simply the applicationId variable, stripping the ".foo". Bug: 79148523,77549386, 110261673 Change-Id: I3b67175e4e11eb4999fad0b158880873f87b4090
1 parent b5b9c6d commit 9ea5864

File tree

15 files changed

+653
-271
lines changed

15 files changed

+653
-271
lines changed

source/IOSResolver/src/IOSResolver.cs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// </copyright>
1616

1717
#if UNITY_IOS
18+
using Google;
1819
using GooglePlayServices;
1920
using Google.JarResolver;
2021
using System;
@@ -526,9 +527,9 @@ exception is TypeInitializationException ||
526527
// If Cocoapod tool auto-installation is enabled try installing on the first update of
527528
// the editor when the editor environment has been initialized.
528529
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS &&
529-
AutoPodToolInstallInEditorEnabled && CocoapodsIntegrationEnabled && !InBatchMode) {
530-
EditorApplication.update -= AutoInstallCocoapods;
531-
EditorApplication.update += AutoInstallCocoapods;
530+
AutoPodToolInstallInEditorEnabled && CocoapodsIntegrationEnabled &&
531+
!ExecutionEnvironment.InBatchMode) {
532+
RunOnMainThread.Run(() => { AutoInstallCocoapods(); }, runNow: false);
532533
}
533534

534535

@@ -537,7 +538,7 @@ exception is TypeInitializationException ||
537538
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS &&
538539
(CocoapodsIntegrationMethod)settings.GetInt(PREFERENCE_COCOAPODS_INTEGRATION_METHOD,
539540
CocoapodsIntegrationUpgradeDefault) == CocoapodsIntegrationMethod.None &&
540-
!InBatchMode && !UpgradeToWorkspaceWarningDisabled) {
541+
!ExecutionEnvironment.InBatchMode && !UpgradeToWorkspaceWarningDisabled) {
541542

542543
switch (EditorUtility.DisplayDialogComplex(
543544
"Warning: CocoaPods integration is disabled!",
@@ -712,13 +713,6 @@ public static bool UseProjectSettings {
712713
/// </summary>
713714
public static bool Enabled { get { return iOSXcodeExtensionLoaded; } }
714715

715-
/// <summary>
716-
/// Whether the editor was launched in batch mode.
717-
/// </summary>
718-
private static bool InBatchMode {
719-
get { return System.Environment.CommandLine.Contains("-batchmode"); }
720-
}
721-
722716
private const float epsilon = 1e-7f;
723717

724718
/// <summary>
@@ -794,7 +788,8 @@ private delegate void LogMessageDelegate(string message, bool verbose = false,
794788
/// <param name="level">Severity of the message.</param>
795789
internal static void Log(string message, bool verbose = false,
796790
LogLevel level = LogLevel.Info) {
797-
logger.Level = (VerboseLoggingEnabled || InBatchMode) ? LogLevel.Verbose : LogLevel.Info;
791+
logger.Level = (VerboseLoggingEnabled || ExecutionEnvironment.InBatchMode) ?
792+
LogLevel.Verbose : LogLevel.Info;
798793
logger.Log(message, level: verbose ? LogLevel.Verbose : level);
799794
}
800795

@@ -1161,7 +1156,6 @@ public static void InstallCocoapodsMenu() {
11611156
/// </summary>
11621157
public static void AutoInstallCocoapods() {
11631158
InstallCocoapodsInteractive(displayAlreadyInstalled: false);
1164-
EditorApplication.update -= AutoInstallCocoapods;
11651159
}
11661160

11671161
/// <summary>
@@ -1277,7 +1271,7 @@ public static void InstallCocoapods(bool interactive, string workingDirectory,
12771271
}
12781272
}
12791273
}
1280-
if (VerboseLoggingEnabled || InBatchMode) {
1274+
if (VerboseLoggingEnabled || ExecutionEnvironment.InBatchMode) {
12811275
installArgs += " --verbose";
12821276
}
12831277

@@ -1772,6 +1766,7 @@ private static void RunCommandsAsync(CommandItem[] commands,
17721766
dialog.autoScrollToBottom = true;
17731767
dialog.bodyText = commands[0].ToString() + "\n";
17741768
dialog.summaryText = summaryText ?? dialog.bodyText;
1769+
dialog.logger = logger;
17751770

17761771
int index = 0;
17771772
var handlerContainer = new DelegateContainer<CommandLine.CompletionHandler>();

source/PlayServicesResolver/src/AndroidSdkManager.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ public static void QueryPackages(string toolPath, string toolArguments,
415415
window.modal = false;
416416
window.progressTitle = window.summaryText;
417417
window.autoScrollToBottom = true;
418+
window.logger = PlayServicesResolver.logger;
418419
window.RunAsync(
419420
toolPath, toolArguments,
420421
(CommandLine.Result result) => {
@@ -544,6 +545,7 @@ private static void DisplayInstallLicenseDialog(
544545
window.bodyText = String.Format("{0} {1}\n\n", toolPath, toolArguments);
545546
window.progressTitle = window.summaryText;
546547
window.autoScrollToBottom = true;
548+
window.logger = PlayServicesResolver.logger;
547549
CommandLine.IOHandler ioHandler = null;
548550
if (licenseResponder != null) ioHandler = licenseResponder.AggregateLine;
549551
PlayServicesResolver.Log(String.Format("{0} {1}", toolPath, toolArguments),
@@ -574,6 +576,7 @@ private static void DisplayLicensesDialog(string licenses, Action<bool> complete
574576
window.yesText = "agree";
575577
window.noText = "decline";
576578
window.result = false;
579+
window.logger = PlayServicesResolver.logger;
577580
window.Repaint();
578581
window.buttonClicked = (TextAreaDialog dialog) => {
579582
window.Close();

source/PlayServicesResolver/src/CommandLine.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace GooglePlayServices
2626
using UnityEditor;
2727
#endif // UNITY_EDITOR
2828

29+
using Google;
30+
2931
public static class CommandLine
3032
{
3133
/// <summary>
@@ -113,6 +115,7 @@ public static StreamData Empty
113115
/// <summary>
114116
/// Asynchronously execute a command line tool, calling the specified delegate on
115117
/// completion.
118+
/// NOTE: In batch mode this will be executed synchronously.
116119
/// </summary>
117120
/// <param name="toolPath">Tool to execute.</param>
118121
/// <param name="arguments">String to pass to the tools' command line.</param>
@@ -122,17 +125,21 @@ public static StreamData Empty
122125
/// <param name="ioHandler">Allows a caller to provide interactive input and also handle
123126
/// both output and error streams from a single delegate.</param>
124127
public static void RunAsync(
125-
string toolPath, string arguments, CompletionHandler completionDelegate,
126-
string workingDirectory = null,
127-
Dictionary<string, string> envVars = null,
128-
IOHandler ioHandler = null)
129-
{
130-
Thread thread = new Thread(new ThreadStart(() => {
131-
Result result = Run(toolPath, arguments, workingDirectory, envVars: envVars,
132-
ioHandler: ioHandler);
133-
completionDelegate(result);
134-
}));
135-
thread.Start();
128+
string toolPath, string arguments, CompletionHandler completionDelegate,
129+
string workingDirectory = null,
130+
Dictionary<string, string> envVars = null,
131+
IOHandler ioHandler = null) {
132+
Action action = () => {
133+
Result result = Run(toolPath, arguments, workingDirectory, envVars: envVars,
134+
ioHandler: ioHandler);
135+
completionDelegate(result);
136+
};
137+
if (ExecutionEnvironment.InBatchMode) {
138+
action();
139+
} else {
140+
Thread thread = new Thread(new ThreadStart(action));
141+
thread.Start();
142+
}
136143
}
137144

138145
/// <summary>

source/PlayServicesResolver/src/CommandLineDialog.cs

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace GooglePlayServices
2626

2727
using Google;
2828

29-
public class CommandLineDialog : TextAreaDialog
29+
internal class CommandLineDialog : TextAreaDialog
3030
{
3131
/// <summary>
3232
/// Forwards the output of the currently executing command to a CommandLineDialog window.
@@ -45,6 +45,8 @@ public class ProgressReporter : CommandLine.LineReader
4545
private volatile int linesReported;
4646
// Command line tool result, set when command line execution is complete.
4747
private volatile CommandLine.Result result = null;
48+
// Logger for messages.
49+
private Google.Logger logger = null;
4850

4951
/// <summary>
5052
/// Event called on the main / UI thread when the outstanding command line tool
@@ -55,12 +57,13 @@ public class ProgressReporter : CommandLine.LineReader
5557
/// <summary>
5658
/// Construct a new reporter.
5759
/// </summary>
58-
public ProgressReporter(CommandLine.IOHandler handler = null)
59-
{
60+
/// <param name="logger">Logger to log command output.</param>
61+
public ProgressReporter(Google.Logger logger) {
6062
textQueue = System.Collections.Queue.Synchronized(new System.Collections.Queue());
6163
maxProgressLines = 0;
6264
linesReported = 0;
6365
LineHandler += CommandLineIOHandler;
66+
this.logger = logger;
6467
Complete = null;
6568
}
6669

@@ -84,18 +87,37 @@ private void CommandLineIOHandler(Process process, StreamWriter stdin,
8487
// Count lines in stdout.
8588
if (data.handle == 0) linesReported += CountLines(data.text);
8689
// Enqueue data for the text view.
87-
textQueue.Enqueue(System.Text.Encoding.UTF8.GetString(data.data));
90+
var newLines = System.Text.Encoding.UTF8.GetString(data.data);
91+
textQueue.Enqueue(newLines);
92+
// Write to the logger.
93+
foreach (var line in CommandLine.SplitLines(newLines)) {
94+
logger.Log(line, level: LogLevel.Verbose);
95+
}
8896
}
8997

9098
/// <summary>
9199
/// Called when the currently executing command completes.
92100
/// </summary>
93101
public void CommandLineToolCompletion(CommandLine.Result result)
94102
{
95-
PlayServicesResolver.Log(
103+
logger.Log(
96104
String.Format("Command completed: {0}", result.message),
97105
level: LogLevel.Verbose);
98106
this.result = result;
107+
if (ExecutionEnvironment.InBatchMode) {
108+
RunOnMainThread.Run(() => { SignalComplete(); });
109+
}
110+
}
111+
112+
/// <summary>
113+
/// Signal the completion event handler.
114+
/// This method *must* be called from the main thread.
115+
/// </summary>
116+
private void SignalComplete() {
117+
if (Complete != null) {
118+
Complete(result);
119+
Complete = null;
120+
}
99121
}
100122

101123
/// <summary>
@@ -141,11 +163,7 @@ public void Update(CommandLineDialog window)
141163
if (result != null)
142164
{
143165
window.progressTitle = "";
144-
if (Complete != null)
145-
{
146-
Complete(result);
147-
Complete = null;
148-
}
166+
SignalComplete();
149167
}
150168
}
151169
}
@@ -154,6 +172,7 @@ public void Update(CommandLineDialog window)
154172
public string progressTitle;
155173
public string progressSummary;
156174
public volatile bool autoScrollToBottom;
175+
public Google.Logger logger = new Google.Logger();
157176

158177
/// <summary>
159178
/// Event delegate called from the Update() method of the window.
@@ -170,12 +189,49 @@ public void Update(CommandLineDialog window)
170189
/// <returns>Reference to the new window.</returns>
171190
public static CommandLineDialog CreateCommandLineDialog(string title)
172191
{
173-
CommandLineDialog window = (CommandLineDialog)EditorWindow.GetWindow(
174-
typeof(CommandLineDialog), true, title);
192+
// In batch mode we simply create the class without instancing the visible window.
193+
CommandLineDialog window = ExecutionEnvironment.InBatchMode ?
194+
new CommandLineDialog() : (CommandLineDialog)EditorWindow.GetWindow(
195+
typeof(CommandLineDialog), true, title);
175196
window.Initialize();
176197
return window;
177198
}
178199

200+
/// <summary>
201+
/// Alternative the Show() method that does not crash in batch mode.
202+
/// </summary>
203+
public void Show() {
204+
Show(false);
205+
}
206+
207+
/// <summary>
208+
/// Alternative Show() method that does not crash in batch mode.
209+
/// </summary>
210+
/// <param name="immediateDisplay">Display the window now.</param>
211+
public void Show(bool immediateDisplay) {
212+
if (!ExecutionEnvironment.InBatchMode) {
213+
base.Show(immediateDisplay);
214+
}
215+
}
216+
217+
/// <summary>
218+
/// Alternative Repaint() method that does not crash in batch mode.
219+
/// </summary>
220+
public void Repaint() {
221+
if (!ExecutionEnvironment.InBatchMode) {
222+
base.Repaint();
223+
}
224+
}
225+
226+
/// <summary>
227+
/// Alternative Close() method that does not crash in batch mode.
228+
/// </summary>
229+
public void Close() {
230+
if (!ExecutionEnvironment.InBatchMode) {
231+
base.Close();
232+
}
233+
}
234+
179235
/// <summary>
180236
/// Initialize all members of the window.
181237
/// </summary>
@@ -209,7 +265,8 @@ public void RunAsync(
209265
string workingDirectory = null, Dictionary<string, string> envVars = null,
210266
CommandLine.IOHandler ioHandler = null, int maxProgressLines = 0)
211267
{
212-
CommandLineDialog.ProgressReporter reporter = new CommandLineDialog.ProgressReporter();
268+
CommandLineDialog.ProgressReporter reporter =
269+
new CommandLineDialog.ProgressReporter(logger);
213270
reporter.maxProgressLines = maxProgressLines;
214271
// Call the reporter from the UI thread from this window.
215272
UpdateEvent += reporter.Update;
@@ -221,7 +278,7 @@ public void RunAsync(
221278
CommandLine.CompletionHandler reporterUpdateDisable =
222279
(CommandLine.Result unusedResult) => { this.UpdateEvent -= reporter.Update; };
223280
reporter.Complete += reporterUpdateDisable;
224-
PlayServicesResolver.Log(String.Format(
281+
logger.Log(String.Format(
225282
"Executing command: {0} {1}", toolPath, arguments), level: LogLevel.Verbose);
226283
CommandLine.RunAsync(toolPath, arguments, reporter.CommandLineToolCompletion,
227284
workingDirectory: workingDirectory, envVars: envVars,

source/PlayServicesResolver/src/Constants.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

source/PlayServicesResolver/src/GradlePreBuildResolver.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ private static void RunGenGradleScript(string args, CommandLine.CompletionHandle
143143
window.summaryText = "Generating and running Gradle prebuild.";
144144
window.progressTitle = window.summaryText;
145145
window.autoScrollToBottom = true;
146+
window.logger = PlayServicesResolver.logger;
146147
window.RunAsync(command, args,
147148
(result) => {
148149
if (result.exitCode != 0) {

0 commit comments

Comments
 (0)