@@ -24,6 +24,8 @@ import (
2424 "path/filepath"
2525 "sort"
2626
27+ "github.com/compose-spec/compose-go/utils"
28+
2729 "github.com/compose-spec/compose-go/dotenv"
2830 "github.com/distribution/distribution/v3/reference"
2931 godigest "github.com/opencontainers/go-digest"
@@ -102,10 +104,19 @@ func (p *Project) ConfigNames() []string {
102104
103105// GetServices retrieve services by names, or return all services if no name specified
104106func (p * Project ) GetServices (names ... string ) (Services , error ) {
107+ services , servicesNotFound := p .getServicesByNames (names ... )
108+ if len (servicesNotFound ) > 0 {
109+ return services , fmt .Errorf ("no such service: %s" , servicesNotFound [0 ])
110+ }
111+ return services , nil
112+ }
113+
114+ func (p * Project ) getServicesByNames (names ... string ) (Services , []string ) {
105115 if len (names ) == 0 {
106116 return p .Services , nil
107117 }
108118 services := Services {}
119+ var servicesNotFound []string
109120 for _ , name := range names {
110121 var serviceConfig * ServiceConfig
111122 for _ , s := range p .Services {
@@ -115,11 +126,12 @@ func (p *Project) GetServices(names ...string) (Services, error) {
115126 }
116127 }
117128 if serviceConfig == nil {
118- return services , fmt .Errorf ("no such service: %s" , name )
129+ servicesNotFound = append (servicesNotFound , name )
130+ continue
119131 }
120132 services = append (services , * serviceConfig )
121133 }
122- return services , nil
134+ return services , servicesNotFound
123135}
124136
125137// GetDisabledService retrieve disabled service by name
@@ -159,34 +171,38 @@ func (p *Project) WithServices(names []string, fn ServiceFunc, options ...Depend
159171 // backward compatibility
160172 options = []DependencyOption {IncludeDependencies }
161173 }
162- return p .withServices (names , fn , map [string ]bool {}, options )
174+ return p .withServices (names , fn , map [string ]bool {}, options , map [ string ] ServiceDependency {} )
163175}
164176
165- func (p * Project ) withServices (names []string , fn ServiceFunc , seen map [string ]bool , options []DependencyOption ) error {
166- services , err := p .GetServices (names ... )
167- if err != nil {
168- return err
177+ func (p * Project ) withServices (names []string , fn ServiceFunc , seen map [string ]bool , options []DependencyOption , dependencies map [string ]ServiceDependency ) error {
178+ services , servicesNotFound := p .getServicesByNames (names ... )
179+ if len (servicesNotFound ) > 0 {
180+ for _ , serviceNotFound := range servicesNotFound {
181+ if dependency , ok := dependencies [serviceNotFound ]; ! ok || dependency .Required {
182+ return fmt .Errorf ("no such service: %s" , serviceNotFound )
183+ }
184+ }
169185 }
170186 for _ , service := range services {
171187 if seen [service .Name ] {
172188 continue
173189 }
174190 seen [service .Name ] = true
175- var dependencies [] string
191+ var dependencies map [ string ] ServiceDependency
176192 for _ , policy := range options {
177193 switch policy {
178194 case IncludeDependents :
179- dependencies = append (dependencies , p .GetDependentsForService (service )... )
195+ dependencies = utils . MapsAppend (dependencies , p .dependentsForService (service ))
180196 case IncludeDependencies :
181- dependencies = append (dependencies , service .GetDependencies () ... )
197+ dependencies = utils . MapsAppend (dependencies , service .DependsOn )
182198 case IgnoreDependencies :
183199 // Noop
184200 default :
185201 return fmt .Errorf ("unsupported dependency policy %d" , policy )
186202 }
187203 }
188204 if len (dependencies ) > 0 {
189- err := p .withServices (dependencies , fn , seen , options )
205+ err := p .withServices (utils . MapKeys ( dependencies ) , fn , seen , options , dependencies )
190206 if err != nil {
191207 return err
192208 }
@@ -199,11 +215,15 @@ func (p *Project) withServices(names []string, fn ServiceFunc, seen map[string]b
199215}
200216
201217func (p * Project ) GetDependentsForService (s ServiceConfig ) []string {
202- var dependent []string
218+ return utils .MapKeys (p .dependentsForService (s ))
219+ }
220+
221+ func (p * Project ) dependentsForService (s ServiceConfig ) map [string ]ServiceDependency {
222+ dependent := make (map [string ]ServiceDependency )
203223 for _ , service := range p .Services {
204- for name := range service .DependsOn {
224+ for name , dependency := range service .DependsOn {
205225 if name == s .Name {
206- dependent = append ( dependent , service .Name )
226+ dependent [ service .Name ] = dependency
207227 }
208228 }
209229 }
0 commit comments