Skip to content

Commit 912ac46

Browse files
committed
Use cross-platform file path lib for compose-file bind sources
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
1 parent 99bd7ed commit 912ac46

8 files changed

Lines changed: 615 additions & 15 deletions

File tree

cli/command/stack/loader/loader.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/docker/cli/cli/compose/loader"
1515
"github.com/docker/cli/cli/compose/schema"
1616
composetypes "github.com/docker/cli/cli/compose/types"
17+
"github.com/docker/docker/pkg/homedir"
1718
"github.com/pkg/errors"
1819
)
1920

@@ -110,6 +111,10 @@ func buildEnvironment(env []string) (map[string]string, error) {
110111
kv := strings.SplitN(s, "=", 2)
111112
result[kv[0]] = kv[1]
112113
}
114+
// patch HOME env var that might be missing on Windows
115+
if _, ok := result["HOME"]; !ok {
116+
result["HOME"] = homedir.Get()
117+
}
113118
return result, nil
114119
}
115120

cli/compose/loader/loader.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package loader
22

33
import (
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
)
@@ -412,32 +412,48 @@ 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, lookupEnv)
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, "~") {
426+
func transformFilePath(origin string, workingDir string, lookupEnv template.Mapping) (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:
433442
home, ok := lookupEnv("HOME")
434443
if !ok {
435444
logrus.Warn("cannot expand '~', because the environment lacks HOME")
436-
return path
445+
return path.Normalize().String(), nil
446+
}
447+
basePath, err := crosspath.ParsePathWithDefaults(home)
448+
if err != nil {
449+
return "", err
450+
}
451+
path, err = basePath.Join(path)
452+
if err != nil {
453+
return "", err
437454
}
438-
return strings.Replace(path, "~", home, 1)
439455
}
440-
return path
456+
return path.Normalize().String(), nil
441457
}
442458

443459
func transformUlimits(data interface{}) (interface{}, error) {

cli/compose/loader/loader_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,3 +1395,57 @@ networks:
13951395
}
13961396
assert.DeepEqual(t, config, expected, cmpopts.EquateEmpty())
13971397
}
1398+
1399+
func TestFilePathsCrossPlat(t *testing.T) {
1400+
cases := []struct {
1401+
path string
1402+
workingDir string
1403+
expected string
1404+
}{
1405+
{
1406+
path: `/var/data`,
1407+
workingDir: `/working/dir`,
1408+
expected: `/var/data`,
1409+
},
1410+
{
1411+
path: `/var/data`,
1412+
workingDir: `c:\working\dir`,
1413+
expected: `/var/data`,
1414+
},
1415+
{
1416+
path: `relative/data`,
1417+
workingDir: `/working/dir`,
1418+
expected: `/working/dir/relative/data`,
1419+
},
1420+
{
1421+
path: `relative/data`,
1422+
workingDir: `c:\working\dir`,
1423+
expected: `c:\working\dir\relative\data`,
1424+
},
1425+
{
1426+
path: `c:\var\data`,
1427+
workingDir: `/working/dir`,
1428+
expected: `c:\var\data`,
1429+
},
1430+
{
1431+
path: `c:\var\data`,
1432+
workingDir: `c:\working\dir`,
1433+
expected: `c:\var\data`,
1434+
},
1435+
{
1436+
path: `relative\data`,
1437+
workingDir: `/working/dir`,
1438+
expected: `/working/dir/relative/data`,
1439+
},
1440+
{
1441+
path: `relative\data`,
1442+
workingDir: `c:\working\dir`,
1443+
expected: `c:\working\dir\relative\data`,
1444+
},
1445+
}
1446+
for _, c := range cases {
1447+
result, err := transformFilePath(c.path, c.workingDir, nil)
1448+
assert.NilError(t, err)
1449+
assert.Equal(t, c.expected, result)
1450+
}
1451+
}

vendor.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ github.com/PuerkitoBio/purell 8a290539e2e8629dbc4e6bad948158f790ec31f4
5656
github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e
5757
github.com/russross/blackfriday 1d6b8e9301e720b08a8938b8c25c018285885438
5858
github.com/shurcooL/sanitized_anchor_name 10ef21a441db47d8b13ebcc5fd2310f636973c77
59+
github.com/simonferquel/crosspath v0.1.0
5960
github.com/sirupsen/logrus v1.0.3
6061
github.com/spf13/cobra 34ceca591bcf34a17a8b7bad5b3ce5f9c165bee5
6162
github.com/spf13/pflag 97afa5e7ca8a08a383cb259e06636b5e2cc7897f

vendor/github.com/simonferquel/crosspath/path.go

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/simonferquel/crosspath/resolver.go

Lines changed: 122 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)