示例#1
0
        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();
            }
示例#3
0
        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();
        }
示例#4
0
        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));
        }
示例#5
0
        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;
                }
            }
        }
示例#6
0
        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());
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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;
            }
        }
示例#11
0
        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));
        }
示例#12
0
        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);
        }
示例#13
0
        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));
        }
示例#14
0
        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..];
示例#15
0
        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));
示例#17
0
 void ICacheable.Load(BinaryReader br)
 {
     DependencyGUID = br.ReadString();
     Flags          = (DependencyFlags)br.ReadInt32();
     VersionRange   = SemVer.Range.Parse(br.ReadString());
 }
示例#18
0
 /// <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;
 }
示例#19
0
 /// <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);
 }
示例#20
0
        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);
            }
        }
示例#21
0
        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;
 }