using System; namespace StellaOps.Concelier.Models; /// /// Helpers for deriving normalized version rules from affected version ranges. /// public static class AffectedVersionRangeExtensions { public static NormalizedVersionRule? ToNormalizedVersionRule(this AffectedVersionRange? range, string? notes = null) { if (range is null) { return null; } var primitives = range.Primitives; var semVerRule = primitives?.SemVer?.ToNormalizedVersionRule(notes); if (semVerRule is not null) { return semVerRule; } var nevraRule = primitives?.Nevra?.ToNormalizedVersionRule(notes); if (nevraRule is not null) { return nevraRule; } var evrRule = primitives?.Evr?.ToNormalizedVersionRule(notes); if (evrRule is not null) { return evrRule; } var scheme = Validation.TrimToNull(range.RangeKind)?.ToLowerInvariant(); return scheme switch { NormalizedVersionSchemes.SemVer => BuildSemVerFallback(range, notes), NormalizedVersionSchemes.Nevra => BuildNevraFallback(range, notes), NormalizedVersionSchemes.Evr => BuildEvrFallback(range, notes), NormalizedVersionSchemes.Apk => BuildApkFallback(range, notes), _ => null, }; } private static NormalizedVersionRule? BuildSemVerFallback(AffectedVersionRange range, string? notes) { var min = Validation.TrimToNull(range.IntroducedVersion); var max = Validation.TrimToNull(range.FixedVersion); var last = Validation.TrimToNull(range.LastAffectedVersion); var resolvedNotes = Validation.TrimToNull(notes); if (string.IsNullOrEmpty(min) && string.IsNullOrEmpty(max) && string.IsNullOrEmpty(last)) { return null; } if (!string.IsNullOrEmpty(max)) { return new NormalizedVersionRule( NormalizedVersionSchemes.SemVer, NormalizedVersionRuleTypes.Range, min: min, minInclusive: min is null ? null : true, max: max, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(last)) { return new NormalizedVersionRule( NormalizedVersionSchemes.SemVer, NormalizedVersionRuleTypes.LessThanOrEqual, max: last, maxInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(min)) { return new NormalizedVersionRule( NormalizedVersionSchemes.SemVer, NormalizedVersionRuleTypes.GreaterThanOrEqual, min: min, minInclusive: true, notes: resolvedNotes); } return null; } private static NormalizedVersionRule? BuildNevraFallback(AffectedVersionRange range, string? notes) { var resolvedNotes = Validation.TrimToNull(notes); var introduced = Validation.TrimToNull(range.IntroducedVersion); var fixedVersion = Validation.TrimToNull(range.FixedVersion); var lastAffected = Validation.TrimToNull(range.LastAffectedVersion); if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Nevra, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Nevra, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Nevra, NormalizedVersionRuleTypes.GreaterThanOrEqual, min: introduced, minInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Nevra, NormalizedVersionRuleTypes.LessThan, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Nevra, NormalizedVersionRuleTypes.LessThanOrEqual, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } return null; } private static NormalizedVersionRule? BuildEvrFallback(AffectedVersionRange range, string? notes) { var resolvedNotes = Validation.TrimToNull(notes); var introduced = Validation.TrimToNull(range.IntroducedVersion); var fixedVersion = Validation.TrimToNull(range.FixedVersion); var lastAffected = Validation.TrimToNull(range.LastAffectedVersion); if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Evr, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Evr, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Evr, NormalizedVersionRuleTypes.GreaterThanOrEqual, min: introduced, minInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Evr, NormalizedVersionRuleTypes.LessThan, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Evr, NormalizedVersionRuleTypes.LessThanOrEqual, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } return null; } private static NormalizedVersionRule? BuildApkFallback(AffectedVersionRange range, string? notes) { var resolvedNotes = Validation.TrimToNull(notes); var introduced = Validation.TrimToNull(range.IntroducedVersion); var fixedVersion = Validation.TrimToNull(range.FixedVersion); var lastAffected = Validation.TrimToNull(range.LastAffectedVersion); if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Apk, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced) && !string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Apk, NormalizedVersionRuleTypes.Range, min: introduced, minInclusive: true, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(introduced)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Apk, NormalizedVersionRuleTypes.GreaterThanOrEqual, min: introduced, minInclusive: true, notes: resolvedNotes); } if (!string.IsNullOrEmpty(fixedVersion)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Apk, NormalizedVersionRuleTypes.LessThan, max: fixedVersion, maxInclusive: false, notes: resolvedNotes); } if (!string.IsNullOrEmpty(lastAffected)) { return new NormalizedVersionRule( NormalizedVersionSchemes.Apk, NormalizedVersionRuleTypes.LessThanOrEqual, max: lastAffected, maxInclusive: true, notes: resolvedNotes); } return null; } }