Skip to content

Commit 2027a34

Browse files
committed
Added builder and awaits for completion before attempting to upload
1 parent 38afa8e commit 2027a34

7 files changed

Lines changed: 111 additions & 120 deletions

File tree

src/VsLinuxDebugger/Commands.Impl.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ public string GetMenuText(int commandId)
1414
{
1515
switch (commandId)
1616
{
17-
case CommandIds.CmdDeployAndDebug: return "Deploy and Debug";
18-
case CommandIds.CmdDeployOnly: return "Deploy Only";
17+
case CommandIds.CmdBuildDeployOnly: return "Build and Deploy";
18+
case CommandIds.CmdBuildDeployDebug: return "Build, Deploy and Debug";
1919
case CommandIds.CmdDebugOnly: return "Debug Only";
20+
////case CommandIds.CmdPublishOnly: return "Publish Only";
21+
////case CommandIds.CmdPublishDebug: return "Publish and Debug";
2022
case CommandIds.CmdShowLog: return "Show Log";
2123
case CommandIds.CmdShowSettings: return "Settings";
2224
default: return $"Unknown CommandId ({commandId})";
@@ -45,10 +47,11 @@ private async Task<bool> ExecuteBuildAsync(BuildOptions buildOptions)
4547
return true;
4648
}
4749

48-
private void InstallMenu(OleMenuCommandService cmd)
50+
private void CreateVsMenu(OleMenuCommandService cmd)
4951
{
50-
AddMenuItem(cmd, CommandIds.CmdDeployAndDebug, SetMenuTextAndVisibility, OnDeployAndDebugAsync);
51-
AddMenuItem(cmd, CommandIds.CmdDeployOnly, SetMenuTextAndVisibility, OnDeployOnlyAsync);
52+
AddMenuItem(cmd, CommandIds.CmdBuildDeployOnly, SetMenuTextAndVisibility, OnBuildDeployAsync);
53+
AddMenuItem(cmd, CommandIds.CmdBuildDeployDebug, SetMenuTextAndVisibility, OnBuildDeployDebugAsync);
54+
////AddMenuItem(cmd, CommandIds.CmdPublishDebug, SetMenuTextAndVisibility, OnPublishDebugAsyc);
5255
AddMenuItem(cmd, CommandIds.CmdDebugOnly, SetMenuTextAndVisibility, OnDebugOnlyAsync);
5356

5457
AddMenuItem(cmd, CommandIds.CmdShowLog, SetMenuTextAndVisibility, OnShowLog);
@@ -62,12 +65,12 @@ private async void OnDebugOnlyAsync(object sender, EventArgs e)
6265
await ExecuteBuildAsync(BuildOptions.Build | BuildOptions.Debug);
6366
}
6467

65-
private async void OnDeployAndDebugAsync(object sender, EventArgs e)
68+
private async void OnBuildDeployDebugAsync(object sender, EventArgs e)
6669
{
6770
await ExecuteBuildAsync(BuildOptions.Build | BuildOptions.Deploy | BuildOptions.Debug);
6871
}
6972

70-
private async void OnDeployOnlyAsync(object sender, EventArgs e)
73+
private async void OnBuildDeployAsync(object sender, EventArgs e)
7174
{
7275
await ExecuteBuildAsync(BuildOptions.Build | BuildOptions.Deploy);
7376
}

src/VsLinuxDebugger/Commands.cs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ private Commands(AsyncPackage package, OleMenuCommandService commandService)
3232
//// _vsExtension = IVsPackageExtensionProvider ?? throw new ArgumentNullException(nameof(vsExtension));
3333
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
3434

35-
InstallMenu(commandService);
36-
37-
//// var menuCommandID = new CommandID(CommandSet, CommandId);
38-
//// var menuItem = new MenuCommand(this.Execute, menuCommandID);
39-
//// commandService.AddCommand(menuItem);
35+
CreateVsMenu(commandService);
4036
}
4137

4238
/// <summary>Gets the instance of the command.</summary>
@@ -79,35 +75,14 @@ private void MessageBox(string message, string title = "Error") => VsShellUtilit
7975
OLEMSGBUTTON.OLEMSGBUTTON_OK,
8076
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
8177

82-
/////// <summary>
83-
/////// This function is the callback used to execute the command when the menu item is clicked.
84-
/////// See the constructor to see how the menu item is associated with this function using
85-
/////// OleMenuCommandService service and MenuCommand class.
86-
/////// </summary>
87-
/////// <param name="sender">Event sender.</param>
88-
/////// <param name="e">Event args.</param>
89-
////private void Execute(object sender, EventArgs e)
90-
////{
91-
//// ThreadHelper.ThrowIfNotOnUIThread();
92-
//// string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
93-
//// string title = "SshDebugCommand";
94-
////
95-
//// // Show a message box to prove we were here
96-
//// VsShellUtilities.ShowMessageBox(
97-
//// this._package,
98-
//// message,
99-
//// title,
100-
//// OLEMSGICON.OLEMSGICON_INFO,
101-
//// OLEMSGBUTTON.OLEMSGBUTTON_OK,
102-
//// OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
103-
////}
104-
10578
/// <summary>VS Menu Command IDs. This must be insync with .vsct values.</summary>
10679
private sealed class CommandIds
10780
{
81+
public const int CmdBuildDeployDebug = 0x1002;
82+
public const int CmdBuildDeployOnly = 0x1001;
10883
public const int CmdDebugOnly = 0x1003;
109-
public const int CmdDeployAndDebug = 0x1001;
110-
public const int CmdDeployOnly = 0x1002;
84+
////public const int CmdPublishOnly = 0x1006;
85+
////public const int CmdPublishDebug= 0x1007;
11186
public const int CmdShowLog = 0x1004;
11287
public const int CmdShowSettings = 0x1005;
11388
public const int LinuxRemoteMainMenu = 0x1000;

src/VsLinuxDebugger/Core/LaunchBuilder.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
using System.Text.Json;
1+
using System;
2+
using System.IO;
3+
using System.Text.Json;
4+
using EnvDTE;
5+
using EnvDTE80;
6+
using Microsoft.VisualStudio.Shell;
27

38
namespace VsLinuxDebugger.Core
49
{
@@ -8,9 +13,20 @@ public class LaunchBuilder
813

914
private UserOptions _options;
1015

11-
public LaunchBuilder(UserOptions o)
16+
public LaunchBuilder(DTE2 dte, Project dteProject, UserOptions o)
1217
{
18+
ThreadHelper.ThrowIfNotOnUIThread();
19+
1320
_options = o;
21+
22+
AssemblyName = dteProject.Properties.Item("AssemblyName").Value.ToString();
23+
ProjectConfigName = dteProject.ConfigurationManager.ActiveConfiguration.ConfigurationName;
24+
ProjectFullName = dteProject.FullName;
25+
ProjectName = dteProject.Name;
26+
SolutionFullName = dte.Solution.FullName;
27+
SolutionDirPath = Path.GetDirectoryName(dte.Solution.FullName);
28+
OutputDirName = dteProject.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
29+
OutputDirFullName = Path.Combine(Path.GetDirectoryName(dteProject.FullName), OutputDirName);
1430
}
1531

1632
public string AssemblyName { get; set; }
@@ -31,7 +47,9 @@ public LaunchBuilder(UserOptions o)
3147

3248
public string SolutionFullName { get; set; }
3349

34-
public string ToJson()
50+
/// <summary>Generates the project's `launch.json` file.</summary>
51+
/// <returns>Returns the local path to the file.</returns>
52+
public string GenerateLaunchJson()
3553
{
3654
////Adapter => !_options.LocalPlinkEnabled ? "ssh.exe" : "";
3755
////
@@ -48,7 +66,11 @@ public string ToJson()
4866
WriteIndented = true,
4967
};
5068

51-
return JsonSerializer.Serialize(launch, opts);
69+
var json = JsonSerializer.Serialize(launch, opts);
70+
71+
throw new NotImplementedException();
72+
73+
return string.Empty;
5274
}
5375
}
5476
}

src/VsLinuxDebugger/Core/RemoteDebugger.cs

Lines changed: 54 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Concurrent;
3-
using System.Collections.Generic;
42
using System.IO;
53
using System.Linq;
64
using System.Threading.Tasks;
@@ -15,6 +13,7 @@ namespace VsLinuxDebugger.Core
1513
public class RemoteDebugger
1614
{
1715
private bool _buildSuccessful;
16+
private TaskCompletionSource<bool> _buildTask = null;
1817
private DTE _dte;
1918
private LaunchBuilder _launchBuilder;
2019
private string _launchJsonPath = string.Empty;
@@ -45,6 +44,20 @@ public async Task<bool> BeginAsync(BuildOptions buildOptions)
4544
return false;
4645
}
4746

47+
if (buildOptions.HasFlag(BuildOptions.Build))
48+
{
49+
BuildBegin();
50+
51+
await _buildTask.Task;
52+
53+
// Work completed
54+
if (!_buildSuccessful)
55+
{
56+
LogOutput("Build was not successful.");
57+
return false;
58+
}
59+
}
60+
4861
using (var ssh = new SshTool(_options, _launchBuilder))
4962
{
5063
if (!ssh.Connect())
@@ -53,39 +66,33 @@ public async Task<bool> BeginAsync(BuildOptions buildOptions)
5366
return false;
5467
}
5568

56-
//// _ssh = ssh;
57-
5869
ssh.TryInstallVsDbg();
5970
ssh.MakeDeploymentFolder();
6071
ssh.CleanDeploymentFolder();
6172

62-
if (buildOptions.HasFlag(BuildOptions.Build))
63-
{
64-
BuildBegin();
65-
}
66-
6773
if (buildOptions.HasFlag(BuildOptions.Deploy))
6874
{
6975
if (_options.RemoteDebugDisplayGui)
7076
ssh.Bash("export DISPLAY=:0");
7177

72-
ssh.UploadFilesAsync();
78+
await ssh.UploadFilesAsync();
7379
}
7480
else if (buildOptions.HasFlag(BuildOptions.Publish))
7581
{
76-
// NOT IMPL
82+
// This is PUBLISH not our 'deployer'
7783
}
7884

7985
if (buildOptions.HasFlag(BuildOptions.Debug))
8086
{
81-
//// AttachToProcess();
87+
BuildDebugAttacher();
8288
}
83-
84-
//// _ssh = null;
8589
}
90+
91+
BuildCleanup();
8692
}
8793
catch (Exception ex)
8894
{
95+
LogOutput($"An error occurred during the build process. {ex.Message}");
8996
return false;
9097
}
9198

@@ -110,10 +117,34 @@ private void AttachToProcess()
110117

111118
private void BuildBegin()
112119
{
120+
// TODO: Disable the menu buttons.
113121
ThreadHelper.ThrowIfNotOnUIThread();
122+
114123
var dte = (DTE)Package.GetGlobalService(typeof(DTE));
115124
BuildEvents = dte.Events.BuildEvents;
116125

126+
_buildTask = new TaskCompletionSource<bool>();
127+
128+
BuildEvents.OnBuildProjConfigDone += (string project, string projectConfig, string platform, string solutionConfig, bool success) =>
129+
{
130+
LogOutput($"Project: {project} --- Success: {success}\n");
131+
132+
if (!success)
133+
BuildCleanup();
134+
135+
_buildSuccessful = Path.GetFileName(project) == $"{_launchBuilder.ProjectName}.csproj" && success;
136+
};
137+
138+
BuildEvents.OnBuildDone += (vsBuildScope scope, vsBuildAction action) =>
139+
{
140+
// TODO: Re-endable the menu buttons.
141+
// Inform system that the task is complete
142+
_buildTask?.TrySetResult(true);
143+
144+
var not = !_buildSuccessful ? "not" : "";
145+
LogOutput($"Build was {not}successful");
146+
};
147+
117148
// For some reason, cleanup isn't actually always ran when there has been an error.
118149
// This removes the fact that if you run a debug attempt, get a file error, that you don't get 2 message boxes, 3 message boxes, etc for each attempt.
119150
////BuildEvents.OnBuildDone -= BuildEvents_OnBuildDoneAsync;
@@ -127,6 +158,7 @@ private void BuildBegin()
127158

128159
private void BuildCleanup()
129160
{
161+
// TODO: The file should be located in the project's output
130162
File.Delete(_launchJsonPath);
131163

132164
//// BuildEvents.OnBuildDone -= BuildEvents_OnBuildDoneAsync;
@@ -136,14 +168,12 @@ private void BuildCleanup()
136168
/// <summary>
137169
/// Start debugging using the remote visual studio server adapter
138170
/// </summary>
139-
private void BuildDebug()
171+
private void BuildDebugAttacher()
140172
{
141-
throw new NotImplementedException();
173+
_launchJsonPath = _launchBuilder.GenerateLaunchJson();
142174

143-
//// _launchJsonPath = _localhost.ToJson();
144-
////
145-
//// var dte = (DTE2)Package.GetGlobalService(typeof(SDTE));
146-
//// dte.ExecuteCommand("DebugAdapterHost.Launch", $"/LaunchJson:\"{_launchJsonPath}\"");
175+
var dte = (DTE2)Package.GetGlobalService(typeof(SDTE));
176+
dte.ExecuteCommand("DebugAdapterHost.Launch", $"/LaunchJson:\"{_launchJsonPath}\"");
147177
}
148178

149179
private bool Initialize()
@@ -155,25 +185,18 @@ private bool Initialize()
155185
if (project == null)
156186
return false;
157187

158-
_launchBuilder = new LaunchBuilder(_options)
159-
{
160-
AssemblyName = project.Properties.Item("AssemblyName").Value.ToString(),
161-
ProjectConfigName = project.ConfigurationManager.ActiveConfiguration.ConfigurationName,
162-
ProjectFullName = project.FullName,
163-
ProjectName = project.Name,
164-
SolutionFullName = dte.Solution.FullName,
165-
SolutionDirPath = Path.GetDirectoryName(dte.Solution.FullName),
166-
OutputDirName = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString(),
167-
OutputDirFullName = Path.Combine(Path.GetDirectoryName(project.FullName), _launchBuilder.OutputDirName),
168-
};
188+
_launchBuilder = new LaunchBuilder(dte, project, _options);
169189

190+
// TODO: Commandline Args
170191
//// if (_options.UseCommandLineArgs)
171192
//// _launchBuilder.CommandLineArgs = ... extract from localSettings.json
172193

173194
return true;
174195
}
175196

176197
/*
198+
* Borrowed from VSMonoDebugger
199+
*
177200
public async Task BuildStartupProjectAsync()
178201
{
179202
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
@@ -228,38 +251,6 @@ private int BuildSolution()
228251
}
229252
*/
230253

231-
/////// <summary>Build is ready for the next steps.</summary>
232-
////private async void BuildEvents_OnBuildDoneAsync(vsBuildScope scope, vsBuildAction action)
233-
////{
234-
//// if (_buildSuccessful)
235-
//// {
236-
//// string errormessage = await TransferFiles2Async().ConfigureAwait(true);
237-
////
238-
//// if (errormessage == "")
239-
//// {
240-
//// StartDebug();
241-
//// BuildCleanup();
242-
//// }
243-
//// else
244-
//// {
245-
//// Output($"Transferring files failed: {errormessage}");
246-
//// }
247-
//// }
248-
////}
249-
////
250-
/////// <summary>The build finised sucessfully and no errors were found.</summary>
251-
////private void BuildEvents_OnBuildProjConfigDone(string project, string projectConfig, string platform, string solutionConfig, bool success)
252-
////{
253-
//// string debugtext = $"Project: {project} --- Success: {success}\n";
254-
////
255-
//// if (!success)
256-
//// {
257-
//// BuildCleanup();
258-
//// }
259-
////
260-
//// _buildSuccessful = Path.GetFileName(project) == _localhost.ProjectName + ".csproj" && success;
261-
////}
262-
263254
private bool IsCSharpProject(Project vsProject)
264255
{
265256
ThreadHelper.ThrowIfNotOnUIThread();

0 commit comments

Comments
 (0)