static BuildInfo() { if (!ReleaseVersion.TryParse(VersionString, out Version)) { Version = new ReleaseVersion(0, 0, 0, ReleaseCandidateLevel.Local); } DateTime.TryParse("@PACKAGE_BUILD_DATE@", out Date); #if DEBUG IsLocalDebugBuild = Version.CandidateLevel == ReleaseCandidateLevel.Local; #else IsLocalDebugBuild = false; #endif }
public void ValidVersion( string expectedSemVer, string expectedWindowsFileVersion, string expectedCFBundleVersion, string expectedCFBundleShortVersionString) { ReleaseVersion version; // parse and assert the semver format ReleaseVersion.TryParse(expectedSemVer, out version).ShouldBeTrue(); version.ToString().ShouldEqual(expectedSemVer); // parse and assert the windows file version format var windowsFileVersion = version.ToWindowsFileVersion(); windowsFileVersion.ToString().ShouldEqual(expectedWindowsFileVersion); version.WithBuild(0).ShouldEqual(ReleaseVersion.FromWindowsFileVersion(windowsFileVersion)); if (expectedCFBundleVersion == null) { Assert.Throws <FormatException> ( () => version.ToString(ReleaseVersionFormat.AppleCFBundleVersion)); } else { version.ToString(ReleaseVersionFormat.AppleCFBundleVersion) .ShouldEqual(expectedCFBundleVersion); } if (expectedCFBundleShortVersionString == null) { Assert.Throws <FormatException> ( () => version.ToString(ReleaseVersionFormat.AppleCFBundleShortVersion)); } else { version.ToString(ReleaseVersionFormat.AppleCFBundleShortVersion) .ShouldEqual(expectedCFBundleShortVersionString); } }
Task <UpdateItem> CheckForUpdatesAsync( CancellationToken cancellationToken = default(CancellationToken)) { var targetChannel = UpdateChannel; return(Task.Run(async() => { var uri = new StringBuilder("https://software.xamarin.com/Service/Updates?v=2&pv") .Append(productId) .Append('=') .Append(BuildInfo.UpdateVersion) .Append("&m=").Append(productId) .Append("&level=").Append(targetChannel) .Append("&alevel=").Append(targetChannel) .Append("&os=").Append(operatingSystem); Log.Debug(TAG, $"querying update service: {uri}"); var httpClient = CreateHttpClient(); var response = (await httpClient.GetAsync( uri.ToString(), HttpCompletionOption.ResponseContentRead, cancellationToken)).EnsureSuccessStatusCode(); // NOTE: the await expression to produce 'manifest' is pulled out // of the null-coalescing expression that follows due to a bug in // mcs that results in an NRE if one object in the query is null // when the await is a subexpression of the null-coalescing chain var manifest = UpdateManifest .Deserialize(await response.Content.ReadAsStreamAsync()); var update = manifest ?.Applications ?.FirstOrDefault() ?.Updates ?.FirstOrDefault(); if (update != null && !update.IsValid) { throw new Exception(Catalog.GetString( "Update service returned an update but it could not be parsed.")); } updateChecksPerformed++; MainThread.Post(() => Prefs.Updater.LastQuery.SetValue(DateTime.UtcNow)); if (update == null) { return null; } Log.Debug(TAG, $"update service returned update: {update.Version} published {update.Date}"); var releaseNotesUrl = $"https://dl.xamarin.com/interactive/updater-release-notes-{update.Version}.html"; try { httpClient = CreateHttpClient(); response = (await httpClient.GetAsync( releaseNotesUrl, HttpCompletionOption.ResponseContentRead, cancellationToken)).EnsureSuccessStatusCode(); update.ReleaseNotes = await response.Content.ReadAsStringAsync(); } catch (Exception e) when(!(e is TaskCanceledException || e is OperationCanceledException)) { Log.Warning(TAG, $"{update.Version} update available but release notes are missing: {releaseNotesUrl}", e); } ReleaseVersion.TryParse(update.Version, out var semver); return new UpdateItem( semver, update.Version, update.ReleaseNotes, targetChannel, update.Url, update.Hash); })); }
internal static void GetInstalledWorkloads(IWorkloadResolver workloadResolver, SdkFeatureBand sdkFeatureBand, InstalledWorkloadsCollection installedWorkloads) { IEnumerable <string> visualStudioWorkloadIds = GetAvailableVisualStudioWorkloads(workloadResolver); HashSet <string> installedWorkloadComponents = new(); // Visual Studio instances contain a large set of packages and we have to perform a linear // search to determine whether a matching SDK was installed and look for each installable // workload from the SDK. The search is optimized to only scan each set of packages once. foreach (ISetupInstance2 instance in GetVisualStudioInstances()) { ISetupPackageReference[] packages = instance.GetPackages(); bool hasMatchingSdk = false; installedWorkloadComponents.Clear(); for (int i = 0; i < packages.Length; i++) { string packageId = packages[i].GetId(); if (string.IsNullOrWhiteSpace(packageId)) { // Visual Studio already verifies the setup catalog at build time. If the package ID is empty // the catalog is likely corrupted. continue; } if (packageId.StartsWith(s_visualStudioSdkPackageIdPrefix)) { // After trimming the package prefix we should be left with a valid semantic version. If we can't // parse the version we'll skip this instance. if (!ReleaseVersion.TryParse(packageId.Substring(s_visualStudioSdkPackageIdPrefix.Length), out ReleaseVersion visualStudioSdkVersion)) { break; } SdkFeatureBand visualStudioSdkFeatureBand = new SdkFeatureBand(visualStudioSdkVersion); // The feature band of the SDK in VS must match that of the SDK on which we're running. if (!visualStudioSdkFeatureBand.Equals(sdkFeatureBand)) { break; } hasMatchingSdk = true; continue; } if (visualStudioWorkloadIds.Contains(packageId, StringComparer.OrdinalIgnoreCase)) { // Normalize back to an SDK style workload ID. installedWorkloadComponents.Add(packageId.Replace('.', '-')); } } if (hasMatchingSdk) { foreach (string id in installedWorkloadComponents) { installedWorkloads.Add(id, $"VS {instance.GetInstallationVersion()}"); } } } }
void ProcessReleaseFile(ReleaseFile releaseFile) { var relativePath = releaseFile.PublishUri; var relativePathFileName = Path.GetFileName(relativePath); var updaterItem = updaterFileRegex.Match(relativePathFileName); if (updaterItem == null || !updaterItem.Success) { return; } releaseFile.ProductType = 11; // no idea! releaseFile.ProductName = ProductName; releaseFile.UpdaterProduct = new XamarinUpdaterProduct { Version = updaterItem.Groups ["version"].Value }; if (UpdateInfoFile != null) { releaseFile.UpdaterProduct.PopulateFromUpdateinfoFile(UpdateInfoFile); } if (UpdaterReleaseNotes != null) { releaseFile.UpdaterProduct.Blurb = string .Join("\n", UpdaterReleaseNotes) .Trim(); } if (!ReleaseVersion.TryParse(releaseFile.UpdaterProduct.Version, out var version)) { return; } if (version.CandidateLevel == ReleaseCandidateLevel.Stable && updaterItem.Groups ["extension"].Value == ".pkg") { releaseFile.UploadEnvironments |= UploadEnvironments.XamarinInstaller; } releaseFile.UploadEnvironments |= UploadEnvironments.XamarinUpdater; switch (version.CandidateLevel) { case ReleaseCandidateLevel.Alpha: releaseFile.UpdaterProduct.Channels = XamarinUpdaterChannels.Alpha; break; case ReleaseCandidateLevel.Beta: case ReleaseCandidateLevel.StableCandidate: releaseFile.UpdaterProduct.Channels = XamarinUpdaterChannels.Alpha | XamarinUpdaterChannels.Beta; break; case ReleaseCandidateLevel.Stable: releaseFile.UpdaterProduct.Channels = XamarinUpdaterChannels.Alpha | XamarinUpdaterChannels.Beta | XamarinUpdaterChannels.Stable; break; } }
PublicationItem ProcessItem(PublicationItem item) { var relativePath = item.RelativePublishUrl.ToString(); var relativePathFileName = Path.GetFileName(relativePath); if (pdbArchiveRegex.IsMatch(relativePathFileName)) { item.RelativePublishUrl = null; return(item); } var updaterItem = updaterFileRegex.Match(relativePathFileName); if (updaterItem == null || !updaterItem.Success) { return(item); } if (string.IsNullOrEmpty(ReleaseName)) { ReleaseName = $"{updaterItem.Groups ["name"]}-{updaterItem.Groups ["version"]}"; } if (UpdateInfoFile != null) { item.UpdaterProduct = UpdaterProduct.FromUpdateInfo( File.ReadAllText(UpdateInfoFile)); } else { item.UpdaterProduct = new UpdaterProduct(); } item.UpdaterProduct.Size = item.Size; item.UpdaterProduct.Version = updaterItem.Groups ["version"].Value; if (UpdaterReleaseNotes != null) { item.UpdaterProduct.ReleaseNotes = string .Join("\n", UpdaterReleaseNotes) .Trim(); } if (ReleaseVersion.TryParse(item.UpdaterProduct.Version, out var version)) { if (version.CandidateLevel == ReleaseCandidateLevel.Stable) { item.RelativePublishEvergreenUrl = new Uri( Path.GetDirectoryName(relativePath) + "/" + updaterItem.Groups ["name"].Value + updaterItem.Groups ["extension"].Value, UriKind.Relative); } switch (version.CandidateLevel) { case ReleaseCandidateLevel.Alpha: item.UpdaterProduct.IsAlpha = true; break; case ReleaseCandidateLevel.Beta: case ReleaseCandidateLevel.StableCandidate: item.UpdaterProduct.IsAlpha = true; item.UpdaterProduct.IsBeta = true; break; case ReleaseCandidateLevel.Stable: item.UpdaterProduct.IsAlpha = true; item.UpdaterProduct.IsBeta = true; item.UpdaterProduct.IsStable = true; break; } } return(item); }