/// <summary> /// Try to get the meta comment text of a script /// </summary> /// <param name="engine"></param> /// <param name="text">text of the entire package</param> /// <param name="commentStartRegexPattern">a regex pattern for comment start</param> /// <param name="commentEndRegexPattern">a regex pattern for comment end</param> /// <param name="metaText">output meta text if valid</param> /// <param name="requiredVersion">output version requirement if valid</param> /// <param name="packref">optional pack reference for logging to know which pack we're talking about.</param> /// <returns>True if the meta comment was found successfully</returns> public static bool TryGetScriptMultilineMetaComment( this IScriptEngine engine, string text, string commentStartRegexPattern, string commentEndRegexPattern, out string metaText, out VersionRequirement requiredVersion, CompletePackageReference packref = null) { metaText = ""; requiredVersion = new VersionRequirement(); var matches = text.MatchGroup( $@"{commentStartRegexPattern}\s+uppm\s+(?<uppmversion>[\d\.]+)\s+(?<packmeta>\{{.*\}})\s+{commentEndRegexPattern}", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline); if (matches == null || matches.Count == 0 || matches["uppmversion"]?.Length <= 0 || matches["packmeta"]?.Length <= 0 ) { engine.Log.Error("{PackRef} doesn't contain valid metadata.", packref?.ToString() ?? "Script"); return(false); } if (UppmVersion.TryParse(matches["uppmversion"].Value, out var minuppmversion, UppmVersion.Inference.Zero)) { requiredVersion.MinimalVersion = minuppmversion; requiredVersion.Valid = minuppmversion <= Uppm.CoreVersion; metaText = matches["packmeta"].Value; if (!requiredVersion.Valid) { Log.Error( "{PackRef} requires at least uppm {$RequiredMinVersion}. " + "It's incompatible with Current version of uppm ({$UppmVersion})", packref?.ToString() ?? "Script", requiredVersion.MinimalVersion, Uppm.CoreVersion); return(false); } return(true); } Log.Error("{PackRef} doesn't contain valid metadata.", packref?.ToString() ?? "Script"); return(false); }
/// <summary> /// Common implementation for <see cref="IScriptEngine.TryGetMeta"/> in case /// package defines metadata as HJSON in a multiline comment /// </summary> /// <param name="engine"></param> /// <param name="text">text of the entire package</param> /// <param name="commentStartRegexPattern">a regex pattern for comment start</param> /// <param name="commentEndRegexPattern">a regex pattern for comment end</param> /// <param name="packMeta">reference to a <see cref="PackageMeta"/>. /// if reference is null a new one will be created and assigned to it</param> /// <param name="requiredVersion">output version requirement if valid</param> /// <param name="packref">optional pack reference for logging to know which pack we're talking about.</param> /// <param name="parentRepo">Optionally a parent repository can be specified. This is used mostly for keeping dependency contexts correct.</param> /// <returns>True if package metadata was parsed successfully</returns> public static bool TryGetCommonHjsonMeta( this IScriptEngine engine, string text, string commentStartRegexPattern, string commentEndRegexPattern, ref PackageMeta packMeta, out VersionRequirement requiredVersion, CompletePackageReference packref = null, string parentRepo = "") { if (!engine.TryGetScriptMultilineMetaComment( text, commentStartRegexPattern, commentEndRegexPattern, out var metatext, out requiredVersion, packref)) { return(false); } packMeta = packMeta ?? new PackageMeta(); packMeta.Text = text; packMeta.RequiredUppmVersion = requiredVersion; if (!engine.TryGetHjsonScriptMultilineMeta( metatext, ref packMeta, packref, parentRepo)) { return(false); } if (engine.TryGetScriptText(text, out var scripttext, parentRepo)) { packMeta.ScriptText = scripttext; return(true); }
/// <summary> /// Try to get <see cref="PackageMeta"/> out of an already extracted HJSON meta text /// </summary> /// <param name="engine"></param> /// <param name="metaText">already extracted meta text in HJSON format</param> /// <param name="packMeta">reference to a <see cref="PackageMeta"/>. /// if reference is null a new one will be created and assigned to it</param> /// <param name="packref">optional pack reference for logging to know which pack we're talking about.</param> /// <param name="parentRepo">Optionally a parent repository can be specified. This is used mostly for keeping dependency contexts correct.</param> /// <returns>True if package metadata was parsed successfully</returns> public static bool TryGetHjsonScriptMultilineMeta( this IScriptEngine engine, string metaText, ref PackageMeta packMeta, CompletePackageReference packref = null, string parentRepo = "") { packMeta = packMeta ?? new PackageMeta(); if (packref != null) { packMeta.Self = packref; } try { PackageMeta.ParseFromHjson(metaText, ref packMeta); } catch (Exception e) { Log.Error(e, "Parsing metadata of {PackRef} threw an exception.", packref?.ToString() ?? "script"); return(false); } return(true); }
/// <inheritdoc /> public bool TryInferPackageReference(PartialPackageReference incomplete, out CompletePackageReference complete) => this.TryInferPackageReferenceFromCollection(_packages.Keys, incomplete, out complete);
/// <inheritdoc /> public bool TryGetMeta(string text, ref PackageMeta packmeta, out VersionRequirement requiredVersion, CompletePackageReference packref) { return(this.TryGetCommonHjsonMeta( text, @"\<\#", @"\#\>", ref packmeta, out requiredVersion, packref, packref.RepositoryUrl)); }
/// <summary> /// Tries to convert a <see cref="PartialPackageReference"/> into a <see cref="CompletePackageReference"/> /// one in the context of an <see cref="IPackageRepository"/> and a provided collection of available packages. /// </summary> /// <param name="repository">Target repository</param> /// <param name="packages">Collection of all available packages supplied by the repository</param> /// <param name="incomplete">The source <see cref="PartialPackageReference"/></param> /// <param name="complete">The output <see cref="CompletePackageReference"/> when found or null when there's no match</param> /// <returns>Whether infering found a valid package or not</returns> public static bool TryInferPackageReferenceFromCollection( this IPackageRepository repository, IEnumerable <CompletePackageReference> packages, PartialPackageReference incomplete, out CompletePackageReference complete) { complete = null; if (incomplete?.Name == null) { return(false); } // should the pack be in this repository? if (!string.IsNullOrWhiteSpace(incomplete.RepositoryUrl) && !incomplete.RepositoryUrl.EqualsCaseless(repository.Url)) { return(false); } // is the pack present in this repository? var candidates = packages.Where(p => p.Name.EqualsCaseless(incomplete.Name)).ToList(); if (candidates.Count == 0) { return(false); } // if special version just check for string equality if (incomplete.IsSpecialVersion) { var candidate = candidates.FirstOrDefault(p => p.Version.EqualsCaseless(incomplete.Version)); if (candidate != null) { complete = candidate; return(true); } } // if no version specified or explicitly "latest" is speciofied then get the latest var getlatest = incomplete.Version == null || incomplete.IsLatest; if (getlatest) { // is a pack explicitly labeled "latest" exists already? var candidate = candidates.FirstOrDefault(p => p.IsLatest); if (candidate != null) { complete = candidate; return(true); } // if not try to get the one with the highest semantical version var version = new UppmVersion(0, 0, 0, 0); foreach (var cand in candidates) { if (cand.IsSemanticalVersion(out var semversion) && version < semversion) { version = semversion; candidate = cand; } } if (candidate != null) { complete = candidate; return(true); } // pack has only special versions or no versions at all return(false); } // if an optionally partial semantic version is explicitly specified if (incomplete.IsSemanticalVersion(out var insemver)) { // get the latest semantic version inside the specified version scope var candidate = candidates.Where(p => { var valid = p.IsSemanticalVersion(out var psemver); if (!valid) { return(false); } for (int i = 0; i < (int)insemver.Scope + 1; i++) { valid = psemver.Components[i] == insemver.Components[i]; } return(valid); }) .OrderByDescending(p => p.IsSemanticalVersion(out var psemver) ? psemver : new UppmVersion(0, 0, 0, 0)) .FirstOrDefault(); if (candidate != null) { complete = candidate; return(true); } } return(false); }