Skip to main content

compose_lens/resolution/
mod.rs

1//! Explicit project paths, references, and default decisions.
2
3mod defaults;
4mod paths;
5mod references;
6
7pub use defaults::{
8    AppliedDefault, ComposeDefaults, ContainerPlatform, DefaultKind, DefaultLocation, DefaultProvider, DefaultRequest,
9    DefaultResolution, DefaultValue, NoDefaults, resolve_defaults,
10};
11pub use paths::{
12    HOME_DIRECTORY_REQUIRED, HostPathKind, INCLUDE_RESOURCE_PATH_BASE_UNAVAILABLE, INCLUDE_RESOURCE_PATH_PLAN_MISMATCH,
13    IncludedResourcePath, IncludedResourcePathResolution, PathContext, PathPurpose, PathResolution, ResolvedHostPath,
14    resolve_included_resource_paths, resolve_paths,
15};
16pub use references::{
17    DISABLED_DEPENDENCY_HEALTHCHECK, INACTIVE_SERVICE_REFERENCE, MISSING_REFERENCE, Reference, ReferenceKind,
18    ReferenceStatus, ReferenceValidation, UNVERIFIED_DEPENDENCY_HEALTHCHECK, validate_references,
19};
20
21use crate::diagnostic::{Diagnostic, DiagnosticCode, Severity};
22use crate::merge::{MergedEntry, MergedProject, MergedValue};
23use crate::profiles::ProfileSelection;
24use crate::source::{SourceId, SourceSpan};
25
26/// A profile selection was created from another merged project.
27pub const SELECTION_PROJECT_MISMATCH: DiagnosticCode =
28    DiagnosticCode::new("compose.resolution.selection-project-mismatch");
29
30pub(crate) fn selection_matches(
31    project: &MergedProject,
32    selection: Option<&ProfileSelection>,
33    diagnostics: &mut Vec<Diagnostic>,
34) -> bool {
35    if selection.is_none_or(|selection| selection.belongs_to(project)) {
36        return true;
37    }
38    diagnostics.push(Diagnostic::new(
39        SELECTION_PROJECT_MISMATCH,
40        Severity::Error,
41        "profile selection does not belong to the merged project",
42    ));
43    false
44}
45
46pub(crate) fn service_entries(project: &MergedProject) -> &[MergedEntry] {
47    project
48        .root()
49        .get("services")
50        .and_then(MergedValue::as_mapping)
51        .unwrap_or_default()
52}
53
54pub(crate) fn service_in_scope(selection: Option<&ProfileSelection>, name: &str) -> bool {
55    selection.is_none_or(|selection| selection.is_active(name))
56}
57
58pub(crate) fn effective_span(value: &MergedValue) -> SourceSpan {
59    value
60        .provenance()
61        .effective_source()
62        .or_else(|| value.provenance().sources().first().copied())
63        .unwrap_or_else(|| SourceSpan::from_valid_offsets(SourceId::new(0), 0, 0))
64}
65
66pub(crate) fn entry_span(entry: &MergedEntry) -> SourceSpan {
67    entry
68        .key_sources()
69        .last()
70        .copied()
71        .or_else(|| entry.key_sources().first().copied())
72        .unwrap_or_else(|| SourceSpan::from_valid_offsets(SourceId::new(0), 0, 0))
73}