Files
git.stella-ops.org/src/Policy/__Libraries/StellaOps.Policy/Licensing/LicenseCompatibilityChecker.cs
2026-01-22 19:08:46 +02:00

70 lines
2.3 KiB
C#

namespace StellaOps.Policy.Licensing;
public sealed record LicenseCompatibilityResult(bool IsCompatible, string? Reason);
public sealed class LicenseCompatibilityChecker
{
public LicenseCompatibilityResult Check(
LicenseDescriptor first,
LicenseDescriptor second,
ProjectContext context)
{
if (first is null)
{
throw new ArgumentNullException(nameof(first));
}
if (second is null)
{
throw new ArgumentNullException(nameof(second));
}
if (IsApacheGpl2Conflict(first.Id, second.Id))
{
return new LicenseCompatibilityResult(
false,
"Apache-2.0 is incompatible with GPL-2.0-only due to patent clauses.");
}
if (first.Category == LicenseCategory.Proprietary
&& second.Category == LicenseCategory.StrongCopyleft)
{
return new LicenseCompatibilityResult(
false,
"Strong copyleft is incompatible with proprietary licensing.");
}
if (second.Category == LicenseCategory.Proprietary
&& first.Category == LicenseCategory.StrongCopyleft)
{
return new LicenseCompatibilityResult(
false,
"Strong copyleft is incompatible with proprietary licensing.");
}
if (context.DistributionModel == DistributionModel.Commercial
&& first.Category == LicenseCategory.StrongCopyleft
&& second.Category == LicenseCategory.StrongCopyleft)
{
return new LicenseCompatibilityResult(
true,
"Strong copyleft pairing detected; ensure redistribution obligations are met.");
}
return new LicenseCompatibilityResult(true, null);
}
private static bool IsApacheGpl2Conflict(string first, string second)
{
return (IsApache(first) && IsGpl2Only(second))
|| (IsApache(second) && IsGpl2Only(first));
}
private static bool IsApache(string licenseId)
=> licenseId.Equals("Apache-2.0", StringComparison.OrdinalIgnoreCase);
private static bool IsGpl2Only(string licenseId)
=> licenseId.Equals("GPL-2.0-only", StringComparison.OrdinalIgnoreCase)
|| licenseId.Equals("GPL-2.0+", StringComparison.OrdinalIgnoreCase);
}