Skip to content

Commit

Permalink
Improve handling of update/modify scenarios
Browse files Browse the repository at this point in the history
We previously hardcoded the major VS version used to build the channel bootstrapper, but this was only necessary for Install scenarios, where we don't know already the channel/installation we're dealing with.

So for update/modify, we pass down the selected instance (or default selected) major version, so we don't select the wrong major version inadvertently.

In addition, for Install, we have a smarter heuristics now that will attempt to load the latest release bootstrapper major version from the official docs on CLI installs for VS, and defaulting to hardcoded "17" for now in the unlikely scenario where we can't reach the page for some reason.

Fixes #123
  • Loading branch information
kzu committed Aug 18, 2022
1 parent eee4173 commit 3aa6458
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/VisualStudio/Commands/ModifyCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override async Task ExecuteAsync(TextWriter output)
// If the channel is not a built-in one, use the existing Uri for updates.
var channel = instance.GetChannel();
if (channel != null)
await installerService.ModifyAsync(instance.GetChannel(), instance.GetSku(), args, output);
await installerService.ModifyAsync(instance.InstallationVersion.Major.ToString(), channel, instance.GetSku(), args, output);
else
await installerService.ModifyAsync(instance.ChannelUri.Replace("/channel", ""), instance.GetSku(), args, output);
}
Expand Down
2 changes: 1 addition & 1 deletion src/VisualStudio/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override async Task ExecuteAsync(TextWriter output)
// If the channel is not a built-in one, use the existing Uri for updates.
var channel = instance.GetChannel();
if (channel != null)
await installerService.UpdateAsync(instance.GetChannel(), instance.GetSku(), args, output);
await installerService.UpdateAsync(instance.InstallationVersion.Major.ToString(), channel, instance.GetSku(), args, output);
else
await installerService.UpdateAsync(instance.ChannelUri.Replace("/channel", ""), instance.GetSku(), args, output);
}
Expand Down
28 changes: 19 additions & 9 deletions src/VisualStudio/InstallerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,43 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Devlooped.Web;

namespace Devlooped
{
class InstallerService
{
public Task InstallAsync(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync(string.Empty, channel, sku, args, output);
{
// determine what's the latest & greatest VS from the docs site
// TODO: if the channel is preview, there' no easy way to get the major version from the web.
var html = HtmlDocument.Load("https://docs.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio");
var vs = html.CssSelectElements("a[href^=https://aka.ms/vs/][href$=/vs_enterprise.exe]")
.Select(e => Regex.Match(e.Attribute("href").Value!, "/(\\d\\d)/").Groups[1].Value)
.OrderByDescending(x => x)
.FirstOrDefault() ?? "17";

return RunAsync(string.Empty, vs, channel, sku, args, output);
}

public Task UpdateAsync(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("update", channel, sku, args, output);
public Task UpdateAsync(string vs, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("update", vs, channel, sku, args, output);

public Task ModifyAsync(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("modify", channel, sku, args, output);
public Task ModifyAsync(string vs, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("modify", vs, channel, sku, args, output);

public Task UpdateAsync(string channelUri, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("update", channelUri, sku, args, output);

public Task ModifyAsync(string channelUri, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("modify", channelUri, sku, args, output);

Task RunAsync(string command, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
Task RunAsync(string command, string vs, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
{
var vs = channel == null || channel == Channel.Release ? "16" : "17";

// Microsoft.VisualStudio.Workload.NetCoreTools > Microsoft.NetCore.Component.DevelopmentTools
if (vs == "17")
if (int.TryParse(vs, out var major) && major >= 17)
args = args.Select(arg => arg == "Microsoft.VisualStudio.Workload.NetCoreTools" ? "Microsoft.NetCore.Component.DevelopmentTools" : arg);

return RunAsync(command, $"https://aka.ms/vs/{vs}/{MapChannel(channel)}", sku, args, output);
Expand Down
1 change: 1 addition & 0 deletions src/VisualStudio/VisualStudio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ See full documentation at $(PackageProjectUrl).
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Devlooped.Web" Version="1.0.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
<PackageReference Include="vswhere" Version="2.8.4" PrivateAssets="all" />
Expand Down

0 comments on commit 3aa6458

Please sign in to comment.