Skip to content

Commit

Permalink
Add support for updating/modifying Build Tools and other installed bu…
Browse files Browse the repository at this point in the history
…ilds

Instead of supporting a fixed list of channels used in our internal well-known list,
also support arbitrary channels for cases where we can readily inspect their URI,
such as for modify and update commands.

This allows us to update/modify even 2017 SKUs, or branch builds.
  • Loading branch information
kzu committed Dec 8, 2020
1 parent e5da6f6 commit 2e2c56a
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 23 deletions.
8 changes: 6 additions & 2 deletions src/VisualStudio.Tests/VisualStudioInstanceExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using VisualStudio;

namespace vswhere
Expand Down Expand Up @@ -30,7 +31,10 @@ public static VisualStudioInstance WithSku(this VisualStudioInstance vsInstance,

public static VisualStudioInstance WithChannel(this VisualStudioInstance vsInstance, Channel channel)
{
vsInstance.ChannelId = productIdByChannel[channel];
vsInstance.ChannelId = productIdByChannel.TryGetValue(channel, out var channelId) ?
vsInstance.ChannelId = channelId :
throw new NotSupportedException("Cannot filter instances by the given channel.");

return vsInstance;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/VisualStudio.Tests/VisualStudioPredicateBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using vswhere;
using Xunit;

Expand Down
2 changes: 1 addition & 1 deletion src/VisualStudio/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ public enum Channel
Release,
Preview,
IntPreview,
Main
Main,
}
}
7 changes: 6 additions & 1 deletion src/VisualStudio/Commands/ModifyCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ public override async Task ExecuteAsync(TextWriter output)

args.AddRange(Descriptor.ExtraArguments);

await installerService.ModifyAsync(instance.GetChannel(), instance.GetSku(), args, 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);
else
await installerService.ModifyAsync(instance.ChannelUri.Replace("/channel", ""), instance.GetSku(), args, output);
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/VisualStudio/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ public override async Task ExecuteAsync(TextWriter output)
instance.InstallationPath
};

await installerService.UpdateAsync(instance.GetChannel(), instance.GetSku(), args, 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);
else
await installerService.UpdateAsync(instance.ChannelUri.Replace("/channel", ""), instance.GetSku(), args, output);
}
}
}
Expand Down
32 changes: 17 additions & 15 deletions src/VisualStudio/InstallerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,33 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace VisualStudio
{
class InstallerService
{
public Task InstallAsync(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output) =>
RunAsync(string.Empty, channel, sku, args, output);
public Task InstallAsync(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync(string.Empty, 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(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("update", 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(Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync("modify", channel, sku, args, output);

async Task RunAsync(string command, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
{
var uri = new StringBuilder("https://aka.ms/vs/16/");
uri = uri.Append(MapChannel(channel));
uri = uri.Append("/vs_");
uri = uri.Append(MapSku(sku));
uri = uri.Append(".exe");
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);

var bootstrapper = await DownloadAsync(uri.ToString(), output);
Task RunAsync(string command, Channel? channel, Sku? sku, IEnumerable<string> args, TextWriter output)
=> RunAsync(command, "https://aka.ms/vs/16/" + MapChannel(channel), sku, args, output);

async Task RunAsync(string command, string channelUri, Sku? sku, IEnumerable<string> args, TextWriter output)
{
var bootstrapper = await DownloadAsync($"{channelUri}/vs_{MapSku(sku)}.exe", output);

var psi = new ProcessStartInfo(bootstrapper)
{
Expand Down
4 changes: 2 additions & 2 deletions src/VisualStudio/VisualStudioInstanceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ public static Sku GetSku(this VisualStudioInstance vsInstance)
_ => throw new ArgumentException($"Invalid SKU {vsInstance.ProductId}. Must be one of {string.Join(", ", Enum.GetNames(typeof(Sku)).Select(x => x.ToLowerInvariant()))}.", "sku"),
};

public static Channel GetChannel(this VisualStudioInstance vsInstance)
public static Channel? GetChannel(this VisualStudioInstance vsInstance)
=> vsInstance.ChannelId switch
{
"VisualStudio.16.Release" => Channel.Release,
"VisualStudio.16.Preview" => Channel.Preview,
"VisualStudio.16.IntPreview" => Channel.IntPreview,
"VisualStudio.16.int.main" => Channel.Main,
_ => throw new ArgumentException($"Invalid ChannelId {vsInstance.ChannelId}. Must be one of {string.Join(", ", Enum.GetNames(typeof(Channel)).Select(x => x.ToLowerInvariant()))}.", "sku"),
_ => null,
};
}
}

0 comments on commit 2e2c56a

Please sign in to comment.