@@ -2,7 +2,6 @@ package loader
22
33import (
44 "fmt"
5- "path"
65 "path/filepath"
76 "reflect"
87 "sort"
@@ -18,6 +17,7 @@ import (
1817 shellwords "github.com/mattn/go-shellwords"
1918 "github.com/mitchellh/mapstructure"
2019 "github.com/pkg/errors"
20+ "github.com/simonferquel/crosspath"
2121 "github.com/sirupsen/logrus"
2222 yaml "gopkg.in/yaml.v2"
2323)
@@ -109,7 +109,7 @@ func loadSections(config map[string]interface{}, configDetails types.ConfigDetai
109109 {
110110 key : "services" ,
111111 fnc : func (config map [string ]interface {}) error {
112- cfg .Services , err = LoadServices (config , configDetails .WorkingDir , configDetails .LookupEnv )
112+ cfg .Services , err = LoadServices (config , configDetails .WorkingDir , configDetails .HomeDir , configDetails . LookupEnv )
113113 return err
114114 },
115115 },
@@ -334,11 +334,11 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error {
334334
335335// LoadServices produces a ServiceConfig map from a compose file Dict
336336// the servicesDict is not validated if directly used. Use Load() to enable validation
337- func LoadServices (servicesDict map [string ]interface {}, workingDir string , lookupEnv template.Mapping ) ([]types.ServiceConfig , error ) {
337+ func LoadServices (servicesDict map [string ]interface {}, workingDir , homeDir string , lookupEnv template.Mapping ) ([]types.ServiceConfig , error ) {
338338 var services []types.ServiceConfig
339339
340340 for name , serviceDef := range servicesDict {
341- serviceConfig , err := LoadService (name , serviceDef .(map [string ]interface {}), workingDir , lookupEnv )
341+ serviceConfig , err := LoadService (name , serviceDef .(map [string ]interface {}), workingDir , homeDir , lookupEnv )
342342 if err != nil {
343343 return nil , err
344344 }
@@ -350,7 +350,7 @@ func LoadServices(servicesDict map[string]interface{}, workingDir string, lookup
350350
351351// LoadService produces a single ServiceConfig from a compose file Dict
352352// the serviceDict is not validated if directly used. Use Load() to enable validation
353- func LoadService (name string , serviceDict map [string ]interface {}, workingDir string , lookupEnv template.Mapping ) (* types.ServiceConfig , error ) {
353+ func LoadService (name string , serviceDict map [string ]interface {}, workingDir , homeDir string , lookupEnv template.Mapping ) (* types.ServiceConfig , error ) {
354354 serviceConfig := & types.ServiceConfig {}
355355 if err := transform (serviceDict , serviceConfig ); err != nil {
356356 return nil , err
@@ -361,7 +361,7 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str
361361 return nil , err
362362 }
363363
364- if err := resolveVolumePaths (serviceConfig .Volumes , workingDir , lookupEnv ); err != nil {
364+ if err := resolveVolumePaths (serviceConfig .Volumes , workingDir , homeDir ); err != nil {
365365 return nil , err
366366 }
367367 return serviceConfig , nil
@@ -402,7 +402,7 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string, l
402402 return nil
403403}
404404
405- func resolveVolumePaths (volumes []types.ServiceVolumeConfig , workingDir string , lookupEnv template. Mapping ) error {
405+ func resolveVolumePaths (volumes []types.ServiceVolumeConfig , workingDir , homeDir string ) error {
406406 for i , volume := range volumes {
407407 if volume .Type != "bind" {
408408 continue
@@ -412,32 +412,43 @@ func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string,
412412 return errors .New (`invalid mount config for type "bind": field Source must not be empty` )
413413 }
414414
415- filePath := expandUser (volume .Source , lookupEnv )
416- // Check for a Unix absolute path first, to handle a Windows client
417- // with a Unix daemon. This handles a Windows client connecting to a
418- // Unix daemon. Note that this is not required for Docker for Windows
419- // when specifying a local Windows path, because Docker for Windows
420- // translates the Windows path into a valid path within the VM.
421- if ! path .IsAbs (filePath ) {
422- filePath = absPath (workingDir , filePath )
415+ filePath , err := transformFilePath (volume .Source , workingDir , homeDir )
416+ if err != nil {
417+ return err
423418 }
419+
424420 volume .Source = filePath
425421 volumes [i ] = volume
426422 }
427423 return nil
428424}
429425
430- // TODO: make this more robust
431- func expandUser (path string , lookupEnv template.Mapping ) string {
432- if strings .HasPrefix (path , "~" ) {
433- home , ok := lookupEnv ("HOME" )
434- if ! ok {
435- logrus .Warn ("cannot expand '~', because the environment lacks HOME" )
436- return path
426+ func transformFilePath (origin string , workingDir , homeDir string ) (string , error ) {
427+ path , err := crosspath .ParsePathWithDefaults (origin )
428+ if err != nil {
429+ return "" , err
430+ }
431+ switch path .Kind () {
432+ case crosspath .Relative :
433+ basePath , err := crosspath .ParsePathWithDefaults (workingDir )
434+ if err != nil {
435+ return "" , err
436+ }
437+ path , err = basePath .Join (path )
438+ if err != nil {
439+ return "" , err
440+ }
441+ case crosspath .HomeRooted :
442+ basePath , err := crosspath .ParsePathWithDefaults (homeDir )
443+ if err != nil {
444+ return "" , err
445+ }
446+ path , err = basePath .Join (path )
447+ if err != nil {
448+ return "" , err
437449 }
438- return strings .Replace (path , "~" , home , 1 )
439450 }
440- return path
451+ return path . String (), nil
441452}
442453
443454func transformUlimits (data interface {}) (interface {}, error ) {
0 commit comments