public async Task CheckVersion() { try { GithubVersion latest = await VersionCheck.GetLatestVersionAsync("Zingabopp", "MultiplayerExtensions"); Log?.Debug($"Latest version is {latest}, released on {latest.ReleaseDate.ToShortDateString()}"); if (PluginMetadata != null) { SemVer.Version currentVer = PluginMetadata.Version; SemVer.Version latestVersion = new SemVer.Version(latest.ToString()); bool updateAvailable = new SemVer.Range($">{currentVer}").IsSatisfied(latestVersion); if (updateAvailable) { Log?.Info($"An update is available!\nNew mod version: {latestVersion}\nCurrent mod version: {currentVer}"); } } } catch (ReleaseNotFoundException ex) { Log?.Warn(ex.Message); } catch (Exception ex) { Log?.Warn($"Error checking latest version: {ex.Message}"); Log?.Debug(ex); } }
private void OnExecute() { if (string.IsNullOrEmpty(Id)) { throw new ArgumentException("Id for 'dependency add' cannot be null or empty!"); } // Create range for dependency // Will throw on failure var range = new SemVer.Range(string.IsNullOrEmpty(Version) ? "*" : Version); var dep = new Dependency(Id, range); // Populate AdditionalInfo if (AdditionalInfo != null) { using var doc = JsonDocument.Parse(AdditionalInfo); if (doc.RootElement.ValueKind != JsonValueKind.Object) { throw new ArgumentException("AdditionalData must be a JSON object!"); } foreach (var p in doc.RootElement.EnumerateObject()) { dep.AdditionalData.Add(p.Name, p.Value); } } // Call dependency handler add Program.DependencyHandler.AddDependency(dep); Console.WriteLine($"Added dependency: {Id} ok!"); Utils.WriteSuccess(); }
public static void UpdateServerHubs(Config _instance) { if (string.IsNullOrEmpty(_instance.ModVersion) || new SemVer.Range($">{_instance.ModVersion}", true).IsSatisfied(IPA.Loader.PluginManager.GetPluginFromId("BeatSaberMultiplayer").Metadata.Version)) { List <string> newVersions = null; if (string.IsNullOrEmpty(_instance.ModVersion)) { newVersions = newServerHubs.Keys.ToList(); } else { newVersions = new SemVer.Range($">{_instance.ModVersion}").Satisfying(newServerHubs.Keys, true).ToList(); } if (newVersions.Count > 0) { List <string> hubs = new List <string>(); foreach (string version in newVersions) { hubs.AddRange(newServerHubs[version].Where(x => !_instance.ServerHubIPs.Contains(x))); } _instance.ServerHubIPs = _instance.ServerHubIPs.Concat(hubs).ToArray(); _instance.ServerHubPorts = _instance.ServerHubPorts.Concat(Enumerable.Repeat(3700, hubs.Count)).ToArray(); Plugin.log.Info($"Added {hubs.Count} new ServerHubs to config!"); } } _instance.ModVersion = IPA.Loader.PluginManager.GetPluginFromId("BeatSaberMultiplayer").Metadata.Version.ToString(); }
public ModPair GetLatest(string id, SemVer.Range range = null) { if (range is null) { range = new SemVer.Range("*"); } if (string.IsNullOrEmpty(id)) { return(null); } // We need to perform a double check to make sure we format this string properly for the backend. // It's horrible and sad, but it must be done. var rangeStr = range.ToString(); var ind = rangeStr.IndexOf('<'); if (ind > 1) { rangeStr = rangeStr.Substring(0, ind) + "," + rangeStr.Substring(ind); } else { ind = rangeStr.IndexOf('>'); if (ind > 1) { rangeStr = rangeStr.Substring(0, ind) + "," + rangeStr.Substring(ind); } } var s = client.DownloadString($"/{id}?req={rangeStr}"); return(JsonSerializer.Deserialize <ModPair>(s)); }
IEnumerator CheckVersion() { Plugin.log.Info("Checking for updates..."); UnityWebRequest www = SongDownloader.GetRequestForUrl($"https://api.github.com/repos/andruzzzhka/BeatSaberMultiplayer/releases"); www.timeout = 10; yield return(www.SendWebRequest()); if (!www.isNetworkError && !www.isHttpError) { JSONNode releases = JSON.Parse(www.downloadHandler.text); JSONNode latestRelease = releases[0]; SemVer.Version currentVer = IPA.Loader.PluginManager.GetPlugin("Beat Saber Multiplayer").Version; SemVer.Version githubVer = new SemVer.Version(latestRelease["tag_name"], true); bool newTag = new SemVer.Range($">{currentVer}").IsSatisfied(githubVer); if (newTag) { Plugin.log.Info($"An update for the mod is available!\nNew mod version: {(string)latestRelease["tag_name"]}\nCurrent mod version: {currentVer}"); _newVersionText.gameObject.SetActive(true); _newVersionText.text = $"Version {(string)latestRelease["tag_name"]}\n of the mod is available!\nCurrent mod version: {currentVer}"; _newVersionText.alignment = TextAlignmentOptions.Center; } } }
public async Task <IList <RegistryInfo> > FindServiceInstancesWithVersionAsync(string name, string version) { var instances = await FindServiceInstancesAsync(name); var range = new SemVer.Range(version); return(instances.Where(x => range.IsSatisfied(x.Version)).ToArray()); }
void ICacheable.Load(BinaryReader br) { DependencyGUID = br.ReadString(); Flags = (DependencyFlags)br.ReadInt32(); var versionRange = br.ReadString(); VersionRange = versionRange == string.Empty ? null : SemVer.Range.Parse(versionRange); }
private async Task <PackageInfo> GetPackageInfoByStringAsync(string packageId, string packageVersionValue, bool preReleased, string repository) { PackageInfo package = null; // if packageVersionValue is null, get the newest version if (packageVersionValue == null || packageVersionValue == "") { PackageOption option = new PackageOption() { packageId = packageId, includePrerelease = preReleased, registry = repository }; IEnumerable <string> versionList = await GetPackageVersionAsync(option.packageId, option.registry, option.includePrerelease); if (versionList != null) { packageVersionValue = versionList.ElementAt(0); } else { return(null); } } SemVer.Version packageVersion = null; SemVer.Range range = null; if (SemVer.Version.TryParse(packageVersionValue, out packageVersion) == true) { // version Console.WriteLine($"Convet to version: {packageId}: {packageVersionValue}"); package = new PackageInfo { packageId = packageId, packageVersion = packageVersion }; } else if (SemVer.Range.TryParse(packageVersionValue, out range)) { // range Console.WriteLine($"Convet to range: {packageId}: {packageVersionValue}"); package = await GetBestMatchPackageVersionsAsync(repository, preReleased, packageId, range); Console.WriteLine($"Find best match: {packageId}: {package?.packageVersion?.ToString()}"); } else { // range of * Console.WriteLine($"Convet to range: {packageId}: {packageVersionValue}"); range = new SemVer.Range("*"); package = await GetBestMatchPackageVersionsAsync(repository, preReleased, packageId, range); Console.WriteLine($"Find best match: {packageId}: {package?.packageVersion?.ToString()}"); } return(package); }
public static bool VersionSatisfiedBy(string range, ElasticsearchVersion version) { var versionRange = new SemVer.Range(range); var satisfied = versionRange.IsSatisfied(version.Version); if (!version.IsSnapshot || satisfied) { return(satisfied); } //Semver can only match snapshot version with ranges on the same major and minor //anything else fails but we want to know e.g 2.4.5-SNAPSHOT satisfied by <5.0.0; var wholeVersion = $"{version.Major}.{version.Minor}.{version.Patch}"; return(versionRange.IsSatisfied(wholeVersion)); }
/// <summary> /// Check if this version is compatible agains an starcounter version /// </summary> /// <param name="starcounterVersion"></param> /// <returns></returns> public bool IsCompatibleWith(string versionCompability) { if (string.IsNullOrEmpty(versionCompability)) { return true; } try { SemVer.Version scVersion = new SemVer.Version(this.StarcounterVersion, true); SemVer.Range versionRange = new SemVer.Range(versionCompability, true); return ((versionRange == null || scVersion == null) || versionRange.IsSatisfied(this.StarcounterVersion, true)); } catch (Exception) { return false; } }
public bool InRange(string range) { var versionRange = new SemVer.Range(range); var satisfied = versionRange.IsSatisfied(this); if (this.ArtifactBuildState != ArtifactBuildState.Released || satisfied) { return(satisfied); } //Semver can only match snapshot version with ranges on the same major and minor //anything else fails but we want to know e.g 2.4.5-SNAPSHOT satisfied by <5.0.0; var wholeVersion = $"{this.Major}.{this.Minor}.{this.Patch}"; return(versionRange.IsSatisfied(wholeVersion)); }
public ModsCheckResult CheckRequiredMods() { if (requiredMods == null || requiredMods.Count == 0) { return(new ModsCheckResult() { satisfied = true }); } ModsCheckResult result = new ModsCheckResult(); result.missingMods = new List <ModEntry>(); result.oudatedMods = new List <ModEntry>(); result.satisfiedMods = new List <ModEntry>(); result.satisfied = true; foreach (var reqMod in requiredMods) { var mod = IllusionInjector.PluginManager.Plugins.FirstOrDefault(x => x.Name == reqMod.name); if (mod != null) { SemVer.Version version = new SemVer.Version(mod.Version); SemVer.Range range = new SemVer.Range(reqMod.version); if (range.IsSatisfied(version)) { result.satisfiedMods.Add(reqMod); } else { result.oudatedMods.Add(reqMod); result.satisfied = false; } } else { result.missingMods.Add(reqMod); result.satisfied = false; } } return(result); }
public static async Task <Tuple <string, SemVer.Version> > DownloadPackageAsync( string owner, string repoName, string projectId, SemVer.Range versionRange, string sourceName, string sourceExtension, string userToken = null, bool force = false) { var packages = await FetchPackagesAsync(owner, repoName, projectId, sourceName, sourceExtension, userToken : userToken); var versionIndex = versionRange.GetSatisfiedVersionIndex(packages.Select(p => p.Item2).ToList()); if (versionIndex == -1) { throw new ArgumentException("Cannot find a package matched version range."); } var package = packages[versionIndex]; var cacheRootPath = GetPackageCacheRoot(); if (Directory.Exists(cacheRootPath) == false) { Directory.CreateDirectory(cacheRootPath); } var saveFileName = Path.Combine( cacheRootPath, string.Format("github~{0}~{1}~{2}~{3}{4}", owner, repoName, sourceName.Replace("*", ""), package.Item2, sourceExtension)); if (File.Exists(saveFileName) == false || force) { using (var httpClient = new HttpClient()) using (var request = new HttpRequestMessage(HttpMethod.Get, package.Item1)) { var response = await httpClient.SendAsync(request); using (var contentStream = await response.Content.ReadAsStreamAsync()) using (var fileStream = new FileStream(saveFileName, System.IO.FileMode.Create, FileAccess.Write)) { await contentStream.CopyToAsync(fileStream); } } } return(Tuple.Create(saveFileName, package.Item2)); }
public async Task <ModPair?> GetLatest(string id, SemVer.Range?range = null) { if (range is null) { range = new SemVer.Range("*"); } if (string.IsNullOrEmpty(id)) { return(null); } // We need to perform a double check to make sure we format this string properly for the backend. // It's horrible and sad, but it must be done. var rangeStr = range.ToString(); var ind = rangeStr.IndexOf('<'); if (ind > 1) { rangeStr = rangeStr.Substring(0, ind) + "," + rangeStr[ind..];
public static int GetSatisfiedVersionIndex(this SemVer.Range versionRange, IList <SemVer.Version> versions) { if (versions.Count == 0) { return(-1); } var highest = (versionRange.ToString().Contains("*") || versionRange.ToString().Contains("x")); var selected = -1; for (int i = 0; i < versions.Count; i++) { if (versionRange.IsSatisfied(versions[i])) { if (selected == -1) { selected = i; } else if (highest) { if (versions[selected] < versions[i]) { selected = i; } } else { if (versions[selected] > versions[i]) { selected = i; } } } } return(selected); }
public void AddDependency(string id, SemVer.Range range) => AddDependency(new Dependency(id, range));
void ICacheable.Load(BinaryReader br) { DependencyGUID = br.ReadString(); Flags = (DependencyFlags)br.ReadInt32(); VersionRange = SemVer.Range.Parse(br.ReadString()); }
/// <summary> /// Marks this <see cref="BaseUnityPlugin"/> as dependent on another plugin. The other plugin will be loaded before this one. /// If the other plugin doesn't exist, what happens depends on the <see cref="Flags"/> parameter. /// </summary> /// <param name="DependencyGUID">The GUID of the referenced plugin.</param> /// <param name="Flags">The flags associated with this dependency definition.</param> public BepInDependency(string DependencyGUID, DependencyFlags Flags = DependencyFlags.HardDependency) { this.DependencyGUID = DependencyGUID; this.Flags = Flags; VersionRange = null; }
/// <summary> /// Marks this <see cref="BaseUnityPlugin"/> as dependent on another plugin. The other plugin will be loaded before this one. /// If the other plugin doesn't exist or is of a version not satisfying <see cref="VersionRange"/>, this plugin will not load and an error will be logged instead. /// </summary> /// <param name="guid">The GUID of the referenced plugin.</param> /// <param name="version">The version range of the referenced plugin.</param> /// <remarks>When version is supplied the dependency is always treated as HardDependency</remarks> public BepInDependency(string guid, string version) : this(guid) { VersionRange = SemVer.Range.Parse(version); }
private static async Task ProcessStep(string projectId, Project.Dependency projectDependency, ProcessContext context) { var versionRange = new SemVer.Range(projectDependency.Version, true); // if already resolved dependency, skip it if (context.PackageMap.ContainsKey(projectId)) { if (versionRange.IsSatisfied(context.PackageMap[projectId]) == false) { throw new InvalidDataException($"Cannot meet version requirement: {projectId} {projectDependency.Version} (but {context.PackageMap[projectId]})"); } return; } // download package Console.WriteLine("Restore: " + projectId); var packageFile = ""; var packageVersion = new SemVer.Version(0, 0, 0); var nugetTargetFrameworkMoniker = string.Empty; var sourceName = projectId; var sourceExtention = ".unitypackage"; if (string.IsNullOrEmpty(projectDependency.SourceType) == false) { var source = projectDependency.SourceType.Split(':'); sourceName = source[0]; if (source.Length > 1) { sourceExtention = source[1]; if (sourceExtention.Contains(".") == false) { sourceExtention = sourceExtention.Insert(0, "."); } } } if (projectDependency.Source != "local" && string.IsNullOrEmpty(context.Options.LocalRepositoryDirectory) == false) { var packages = LocalPackage.GetPackages(context.Options.LocalRepositoryDirectory, projectId); var versionIndex = versionRange.GetSatisfiedVersionIndex(packages.Select(x => x.Item2).ToList()); if (versionIndex != -1) { packageFile = packages[versionIndex].Item1; packageVersion = packages[versionIndex].Item2; } } if (string.IsNullOrEmpty(packageFile) == false) { } else if (projectDependency.Source == "local") { var packages = LocalPackage.GetPackages(context.Options.LocalRepositoryDirectory ?? "", projectId); var versionIndex = versionRange.GetSatisfiedVersionIndex(packages.Select(x => x.Item2).ToList()); if (versionIndex == -1) { throw new InvalidOperationException("Cannot find package from local repository: " + projectId); } packageFile = packages[versionIndex].Item1; packageVersion = packages[versionIndex].Item2; } else if (projectDependency.Source.StartsWith("github:")) { var parts = projectDependency.Source.Substring(7).Split('/'); if (parts.Length != 2) { throw new InvalidDataException("Cannot determine github repo information from url: " + projectDependency.Source); } var r = await GithubPackage.DownloadPackageAsync(parts[0], parts[1], projectId, versionRange, sourceName, sourceExtention, context.Options.Token); packageFile = r.Item1; packageVersion = r.Item2; } else if (projectDependency.Source.StartsWith("nuget:")) { nugetTargetFrameworkMoniker = projectDependency.Source.Substring(6); var r = NugetPackage.DownloadPackage(projectId, projectDependency.Version); packageFile = r.Item1; packageVersion = r.Item2; } else { throw new InvalidOperationException("Cannot recognize source: " + projectDependency.Source); } context.PackageMap.Add(projectId, packageVersion); if (string.IsNullOrEmpty(nugetTargetFrameworkMoniker)) { var projectFile = Path.Combine(context.OutputDir, $"Assets/UnityPackages/{projectId}.unitypackage.json"); // apply package if (sourceExtention == ".zip") { var isCreateProjectFile = SourcePackage.ExtractUnityPackage(packageFile, context.OutputDir, projectId, projectDependency.IncludeExtra, projectDependency.IncludeMerged); if (isCreateProjectFile) { var p = new Project { Id = projectId, Version = packageVersion.ToString() }; p.Description = $"Source package"; p.Files = new List <JToken>() { JToken.FromObject($"Assets/UnityPackages/{projectId}") }; var jsonSettings = new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore, }; File.WriteAllText(projectFile, JsonConvert.SerializeObject(p, Formatting.Indented, jsonSettings)); File.WriteAllBytes(projectFile + ".meta", Packer.GenerateMeta(projectFile, projectFile).Item2); } } else { Extracter.ExtractUnityPackage(packageFile, context.OutputDir, projectId, projectDependency.IncludeExtra, projectDependency.IncludeMerged); } // deep into dependencies if (File.Exists(projectFile)) { var project = Project.Load(projectFile); if (project.MergedDependencies != null && projectDependency.IncludeMerged) { foreach (var d in project.MergedDependencies) { if (context.PackageMap.ContainsKey(d.Key) == false) { context.PackageMap[d.Key] = new SemVer.Version(d.Value.Version, true); } } } if (project.Dependencies != null) { foreach (var d in project.Dependencies) { context.DepQueue.Enqueue(d); } } } } else { // apply package NugetPackage.ExtractPackage(projectId, packageVersion.ToString(), nugetTargetFrameworkMoniker, context.OutputDir); // create proxy project file var outputDir = Path.Combine(context.OutputDir, $"Assets/UnityPackages/{projectId}"); var projectAssetPath = $"Assets/UnityPackages/{projectId}.unitypackage.json"; var projectFile = Path.Combine(context.OutputDir, projectAssetPath); var p = new Project { Id = projectId, Version = packageVersion.ToString() }; p.Description = $"Nuget package (TFM:{nugetTargetFrameworkMoniker})"; p.Files = Directory.GetFiles(outputDir, "*") .Where(f => Path.GetExtension(f).ToLower() != ".meta") .Select(f => JToken.FromObject(f.Substring(outputDir.Length + 1).Replace("\\", "/"))).ToList(); var jsonSettings = new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore, }; File.WriteAllText(projectFile, JsonConvert.SerializeObject(p, Formatting.Indented, jsonSettings)); File.WriteAllBytes(projectFile + ".meta", Packer.GenerateMeta(projectFile, projectAssetPath).Item2); } }
private async Task <PackageInfo> GetBestMatchPackageVersionsAsync(string registry, bool includePrerelease, string packageId, SemVer.Range range) { PackageOption option = new PackageOption { packageId = packageId, includePrerelease = includePrerelease, registry = registry }; Console.WriteLine($"Try to find best match: {packageId}: {range.ToString()}"); IEnumerable <string> versionValues = await GetPackageVersionAsync(option.packageId, option.registry, option.includePrerelease); IEnumerable <SemVer.Version> versions = versionValues?.Select(x => new SemVer.Version(x, true)); if (versions == null) { return(null); } SemVer.Version bestMatchVersion = range.MaxSatisfying(versions); if (bestMatchVersion == null) { bestMatchVersion = versions.OrderByDescending(x => x).FirstOrDefault(); } return(new PackageInfo { packageId = packageId, packageVersion = bestMatchVersion }); }
public Dependency(string id, SemVer.Range versionRange) { Id = id; VersionRange = versionRange; }