chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
 
namespace OpenTap.Package
{
    /// <summary>
    /// Exception thrown when ImageSpecifier.Resolve fails.
    /// </summary>
    public class ImageResolveException : AggregateException
    {
        internal ImageSpecifier Image { get; }
        internal ImmutableArray<PackageDef> InstalledPackages { get; }
        internal ImageResolution Result { get; }
 
        internal ImageResolveException(ImageResolution result, ImageSpecifier image,
            ImmutableArray<PackageDef> installedPackages)
        {
            Result = result;
            Image = image;
            InstalledPackages = installedPackages;
        }
 
        /// <summary>
        /// The description of the resolution error.
        /// </summary>
        public override string Message => ToString();
 
        /// <summary>
        /// Convert the resolution error to a string
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            var unsatisfiedDependencies = new List<PackageDef>();
            if (Result is FailedImageResolution fir && fir.resolveProblems is not GenericResolutionProblem)
            {
                return fir.ToString();
            }
            
            foreach (var pkg in InstalledPackages)
            {
                if (!pkg.Dependencies.All(dep => isSatisfied(dep, InstalledPackages)))
                    unsatisfiedDependencies.Add(pkg);
            }
 
            if (unsatisfiedDependencies.Any())
            {
                var sb = new StringBuilder();
                var namePadding = unsatisfiedDependencies.Max(n => n.Name.Length);
                foreach (var sat in unsatisfiedDependencies)
                {
                    var missingDeps = sat.Dependencies.Where(dep => !isSatisfied(dep, InstalledPackages)).ToArray();
                    missingDeps = missingDeps.Where(m =>
                        this.Image.Packages.Where(p => p.Name == m.Name)
                            .All(requested => !m.Version.IsSatisfiedBy(requested.Version))).ToArray();
                    if (missingDeps.Any())
                    {
                        string missingMsg = string.Join(" and ",
                            missingDeps.Select(pkg => $"{pkg.Name}:{pkg.Version}"));
                        sb.AppendLine($"{sat.Name.PadRight(namePadding)} missing {missingMsg}");
                    }
                }
 
                return $"{sb} ({Image} from {string.Join(", ", Image.Repositories)})";
            }
 
            return Result.ToString();
        }
 
        static bool isSatisfied(PackageDependency dep, IEnumerable<PackageDef> InstalledPackages)
        {
            foreach (var i in InstalledPackages)
            {
                if (i.Name == dep.Name)
                {
                    if (dep.Version.IsSatisfiedBy(i.Version.AsExactSpecifier()))
                        return true;
                }
            }
 
            return false;
        }
 
 
        /// <summary>
        /// Dependency graph specified in Dot notation
        /// </summary>
        [Obsolete("This will always be null.")]
        public string DotGraph { get; private set; }
    }
}