Skip to content

Commit 595bfa2

Browse files
authored
Merge pull request moby#3908 from gabriel-samfira/handle-platform-file-paths
Handle file paths base on target platform
2 parents b8294e9 + f1657ec commit 595bfa2

File tree

8 files changed

+123
-77
lines changed

8 files changed

+123
-77
lines changed

client/llb/fileop.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ func Mkdir(p string, m os.FileMode, opt ...MkdirOption) *FileAction {
145145
for _, o := range opt {
146146
o.SetMkdirOption(&mi)
147147
}
148+
148149
return &FileAction{
149150
action: &fileActionMkdir{
150151
file: p,
@@ -447,7 +448,6 @@ func Copy(input CopyInput, src, dest string, opts ...CopyOption) *FileAction {
447448
for _, o := range opts {
448449
o.SetCopyOption(&mi)
449450
}
450-
451451
return &FileAction{
452452
action: &fileActionCopy{
453453
state: state,
@@ -523,22 +523,19 @@ func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base
523523

524524
func (a *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
525525
p := path.Clean(a.src)
526+
dir := "/"
527+
var err error
526528
if !path.IsAbs(p) {
527529
if a.state != nil {
528-
dir, err := a.state.GetDir(ctx)
529-
if err != nil {
530-
return "", err
531-
}
532-
p = path.Join("/", dir, p)
530+
dir, err = a.state.GetDir(ctx)
533531
} else if a.fas != nil {
534-
dir, err := a.fas.state.GetDir(ctx)
535-
if err != nil {
536-
return "", err
537-
}
538-
p = path.Join("/", dir, p)
532+
dir, err = a.fas.state.GetDir(ctx)
533+
}
534+
if err != nil {
535+
return "", err
539536
}
540537
}
541-
return p, nil
538+
return path.Join(dir, p), nil
542539
}
543540

544541
func (a *fileActionCopy) addCaps(f *FileOp) {

client/llb/meta.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/google/shlex"
1111
"github.com/moby/buildkit/solver/pb"
1212
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
13+
"github.com/pkg/errors"
1314
)
1415

1516
type contextKeyT string
@@ -78,7 +79,7 @@ func dirf(value string, replace bool, v ...interface{}) StateOption {
7879
if !path.IsAbs(value) {
7980
prev, err := getDir(s)(ctx, c)
8081
if err != nil {
81-
return nil, err
82+
return nil, errors.Wrap(err, "getting dir from state")
8283
}
8384
if prev == "" {
8485
prev = "/"

client/llb/meta_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@ import (
44
"context"
55
"testing"
66

7+
"github.com/stretchr/testify/assert"
78
"github.com/stretchr/testify/require"
89
)
910

1011
func TestRelativeWd(t *testing.T) {
1112
st := Scratch().Dir("foo")
12-
require.Equal(t, getDirHelper(t, st), "/foo")
13+
assert.Equal(t, getDirHelper(t, st), "/foo")
1314

1415
st = st.Dir("bar")
15-
require.Equal(t, getDirHelper(t, st), "/foo/bar")
16+
assert.Equal(t, getDirHelper(t, st), "/foo/bar")
1617

1718
st = st.Dir("..")
18-
require.Equal(t, getDirHelper(t, st), "/foo")
19+
assert.Equal(t, getDirHelper(t, st), "/foo")
1920

2021
st = st.Dir("/baz")
21-
require.Equal(t, getDirHelper(t, st), "/baz")
22+
assert.Equal(t, getDirHelper(t, st), "/baz")
2223

2324
st = st.Dir("../../..")
24-
require.Equal(t, getDirHelper(t, st), "/")
25+
assert.Equal(t, getDirHelper(t, st), "/")
2526
}
2627

2728
func getDirHelper(t *testing.T, s State) string {

frontend/dockerfile/dockerfile2llb/convert.go

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS
360360
if d.stage.BaseName == emptyImageName {
361361
d.state = llb.Scratch()
362362
d.image = emptyImage(platformOpt.targetPlatform)
363+
d.platform = &platformOpt.targetPlatform
363364
continue
364365
}
365366
func(i int, d *dispatchState) {
@@ -486,11 +487,7 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS
486487

487488
// make sure that PATH is always set
488489
if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok {
489-
var pathOS string
490-
if d.platform != nil {
491-
pathOS = d.platform.OS
492-
}
493-
d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv(pathOS))
490+
d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv(d.platform.OS))
494491
}
495492

496493
// initialize base metadata from image conf
@@ -899,6 +896,7 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
899896
st := llb.Scratch().Dir(sourcePath).File(
900897
llb.Mkfile(f, 0755, []byte(data)),
901898
dockerui.WithInternalName("preparing inline document"),
899+
llb.Platform(*d.platform),
902900
)
903901

904902
mount := llb.AddMount(destPath, st, llb.SourcePath(sourcePath), llb.Readonly)
@@ -1002,12 +1000,20 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
10021000
}
10031001

10041002
func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bool, opt *dispatchOpt) error {
1005-
d.state = d.state.Dir(c.Path)
1006-
wd := c.Path
1007-
if !path.IsAbs(c.Path) {
1008-
wd = path.Join("/", d.image.Config.WorkingDir, wd)
1003+
wd, err := system.NormalizeWorkdir(d.image.Config.WorkingDir, c.Path, d.platform.OS)
1004+
if err != nil {
1005+
return errors.Wrap(err, "normalizing workdir")
10091006
}
1007+
1008+
// NormalizeWorkdir returns paths with platform specific separators. For Windows
1009+
// this will be of the form: \some\path, which is needed later when we pass it to
1010+
// HCS.
10101011
d.image.Config.WorkingDir = wd
1012+
1013+
// From this point forward, we can use UNIX style paths.
1014+
wd = system.ToSlash(wd, d.platform.OS)
1015+
d.state = d.state.Dir(wd)
1016+
10111017
if commit {
10121018
withLayer := false
10131019
if wd != "/" {
@@ -1026,6 +1032,7 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
10261032
d.state = d.state.File(llb.Mkdir(wd, 0755, mkdirOpt...),
10271033
llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, c.String(), env)), d.prefixPlatform, &platform, env)),
10281034
location(opt.sourceMap, c.Location()),
1035+
llb.Platform(*d.platform),
10291036
)
10301037
withLayer = true
10311038
}
@@ -1035,11 +1042,11 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
10351042
}
10361043

10371044
func dispatchCopy(d *dispatchState, cfg copyConfig) error {
1038-
pp, err := pathRelativeToWorkingDir(d.state, cfg.params.DestPath)
1045+
dest, err := pathRelativeToWorkingDir(d.state, cfg.params.DestPath, *d.platform)
10391046
if err != nil {
10401047
return err
10411048
}
1042-
dest := path.Join("/", pp)
1049+
10431050
if cfg.params.DestPath == "." || cfg.params.DestPath == "" || cfg.params.DestPath[len(cfg.params.DestPath)-1] == filepath.Separator {
10441051
dest += string(filepath.Separator)
10451052
}
@@ -1137,6 +1144,11 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
11371144
a = a.Copy(st, f, dest, opts...)
11381145
}
11391146
} else {
1147+
src, err = system.NormalizePath("/", src, d.platform.OS, false)
1148+
if err != nil {
1149+
return errors.Wrap(err, "removing drive letter")
1150+
}
1151+
11401152
opts := append([]llb.CopyOption{&llb.CopyInfo{
11411153
Mode: mode,
11421154
FollowSymlinks: true,
@@ -1148,9 +1160,9 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
11481160
}}, copyOpt...)
11491161

11501162
if a == nil {
1151-
a = llb.Copy(cfg.source, filepath.Join("/", src), dest, opts...)
1163+
a = llb.Copy(cfg.source, src, dest, opts...)
11521164
} else {
1153-
a = a.Copy(cfg.source, filepath.Join("/", src), dest, opts...)
1165+
a = a.Copy(cfg.source, src, dest, opts...)
11541166
}
11551167
}
11561168
}
@@ -1159,10 +1171,14 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
11591171
commitMessage.WriteString(" <<" + src.Path)
11601172

11611173
data := src.Data
1162-
f := src.Path
1174+
f, err := system.CheckSystemDriveAndRemoveDriveLetter(src.Path, d.platform.OS)
1175+
if err != nil {
1176+
return errors.Wrap(err, "removing drive letter")
1177+
}
11631178
st := llb.Scratch().File(
11641179
llb.Mkfile(f, 0644, []byte(data)),
11651180
dockerui.WithInternalName("preparing inline document"),
1181+
llb.Platform(*d.platform),
11661182
)
11671183

11681184
opts := append([]llb.CopyOption{&llb.CopyInfo{
@@ -1171,9 +1187,9 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
11711187
}}, copyOpt...)
11721188

11731189
if a == nil {
1174-
a = llb.Copy(st, f, dest, opts...)
1190+
a = llb.Copy(st, system.ToSlash(f, d.platform.OS), dest, opts...)
11751191
} else {
1176-
a = a.Copy(st, f, dest, opts...)
1192+
a = a.Copy(st, filepath.ToSlash(f), dest, opts...)
11771193
}
11781194
}
11791195

@@ -1204,7 +1220,9 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
12041220
d.cmdIndex-- // prefixCommand increases it
12051221
pgName := prefixCommand(d, name, d.prefixPlatform, &platform, env)
12061222

1207-
var copyOpts []llb.ConstraintsOpt
1223+
copyOpts := []llb.ConstraintsOpt{
1224+
llb.Platform(*d.platform),
1225+
}
12081226
copy(copyOpts, fileOpt)
12091227
copyOpts = append(copyOpts, llb.ProgressGroup(pgID, pgName, true))
12101228

@@ -1397,15 +1415,24 @@ func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instru
13971415
return commitToHistory(&d.image, "ARG "+strings.Join(commitStrs, " "), false, nil, d.epoch)
13981416
}
13991417

1400-
func pathRelativeToWorkingDir(s llb.State, p string) (string, error) {
1401-
if path.IsAbs(p) {
1402-
return p, nil
1403-
}
1404-
dir, err := s.GetDir(context.TODO())
1418+
func pathRelativeToWorkingDir(s llb.State, p string, platform ocispecs.Platform) (string, error) {
1419+
dir, err := s.GetDir(context.TODO(), llb.Platform(platform))
14051420
if err != nil {
14061421
return "", err
14071422
}
1408-
return path.Join(dir, p), nil
1423+
1424+
if len(p) == 0 {
1425+
return dir, nil
1426+
}
1427+
p, err = system.CheckSystemDriveAndRemoveDriveLetter(p, platform.OS)
1428+
if err != nil {
1429+
return "", errors.Wrap(err, "removing drive letter")
1430+
}
1431+
1432+
if system.IsAbs(p, platform.OS) {
1433+
return system.NormalizePath("/", p, platform.OS, false)
1434+
}
1435+
return system.NormalizePath(dir, p, platform.OS, false)
14091436
}
14101437

14111438
func addEnv(env []string, k, v string) []string {

frontend/gateway/container/container.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/moby/buildkit/session/secrets"
1414
"github.com/moby/buildkit/util/bklog"
15+
"github.com/moby/buildkit/util/system"
1516

1617
"github.com/moby/buildkit/cache"
1718
"github.com/moby/buildkit/executor"
@@ -92,7 +93,7 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s
9293
cm = refs[m.Input].Worker.CacheManager()
9394
}
9495
return cm.New(ctx, ref, g)
95-
})
96+
}, platform.OS)
9697
if err != nil {
9798
for i := len(p.Actives) - 1; i >= 0; i-- { // call in LIFO order
9899
p.Actives[i].Ref.Release(context.TODO())
@@ -142,7 +143,7 @@ type MountMutableRef struct {
142143

143144
type MakeMutable func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error)
144145

145-
func PrepareMounts(ctx context.Context, mm *mounts.MountManager, cm cache.Manager, g session.Group, cwd string, mnts []*opspb.Mount, refs []*worker.WorkerRef, makeMutable MakeMutable) (p PreparedMounts, err error) {
146+
func PrepareMounts(ctx context.Context, mm *mounts.MountManager, cm cache.Manager, g session.Group, cwd string, mnts []*opspb.Mount, refs []*worker.WorkerRef, makeMutable MakeMutable, platform string) (p PreparedMounts, err error) {
146147
// loop over all mounts, fill in mounts, root and outputs
147148
for i, m := range mnts {
148149
var (
@@ -265,7 +266,7 @@ func PrepareMounts(ctx context.Context, mm *mounts.MountManager, cm cache.Manage
265266
} else {
266267
mws := MountWithSession(mountable, g)
267268
dest := m.Dest
268-
if !filepath.IsAbs(filepath.Clean(dest)) {
269+
if !system.IsAbs(filepath.Clean(dest), platform) {
269270
dest = filepath.Join("/", cwd, dest)
270271
}
271272
mws.Dest = dest

solver/llbsolver/file/backend.go

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"log"
66
"os"
77
"path/filepath"
8+
"runtime"
89
"strings"
910
"time"
1011

@@ -13,6 +14,7 @@ import (
1314
"github.com/moby/buildkit/snapshot"
1415
"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes"
1516
"github.com/moby/buildkit/solver/pb"
17+
"github.com/moby/buildkit/util/system"
1618
"github.com/pkg/errors"
1719
copy "github.com/tonistiigi/fsutil/copy"
1820
)
@@ -66,7 +68,7 @@ func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Cho
6668
}
6769

6870
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.User, idmap *idtools.IdentityMapping) error {
69-
p, err := fs.RootPath(d, filepath.Join("/", action.Path))
71+
p, err := fs.RootPath(d, action.Path)
7072
if err != nil {
7173
return err
7274
}
@@ -126,7 +128,10 @@ func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *cop
126128

127129
func rm(ctx context.Context, d string, action pb.FileActionRm) error {
128130
if action.AllowWildcard {
129-
src := cleanPath(action.Path)
131+
src, err := cleanPath(action.Path)
132+
if err != nil {
133+
return errors.Wrap(err, "cleaning path")
134+
}
130135
m, err := copy.ResolveWildcards(d, src, false)
131136
if err != nil {
132137
return err
@@ -167,9 +172,14 @@ func rmPath(root, src string, allowNotFound bool) error {
167172
}
168173

169174
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.User, idmap *idtools.IdentityMapping) error {
170-
srcPath := cleanPath(action.Src)
171-
destPath := cleanPath(action.Dest)
172-
175+
srcPath, err := cleanPath(action.Src)
176+
if err != nil {
177+
return errors.Wrap(err, "cleaning source path")
178+
}
179+
destPath, err := cleanPath(action.Dest)
180+
if err != nil {
181+
return errors.Wrap(err, "cleaning path")
182+
}
173183
if !action.CreateDestPath {
174184
p, err := fs.RootPath(dest, filepath.Join("/", action.Dest))
175185
if err != nil {
@@ -244,19 +254,6 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
244254
return nil
245255
}
246256

247-
func cleanPath(s string) string {
248-
s2 := filepath.Join("/", s)
249-
if strings.HasSuffix(s, "/.") {
250-
if s2 != "/" {
251-
s2 += "/"
252-
}
253-
s2 += "."
254-
} else if strings.HasSuffix(s, "/") && s2 != "/" {
255-
s2 += "/"
256-
}
257-
return s2
258-
}
259-
260257
type Backend struct {
261258
}
262259

@@ -349,3 +346,21 @@ func (fb *Backend) Copy(ctx context.Context, m1, m2, user, group fileoptypes.Mou
349346

350347
return docopy(ctx, src, dest, action, u, mnt2.m.IdentityMapping())
351348
}
349+
350+
func cleanPath(s string) (string, error) {
351+
s, err := system.CheckSystemDriveAndRemoveDriveLetter(s, runtime.GOOS)
352+
if err != nil {
353+
return "", errors.Wrap(err, "removing drive letter")
354+
}
355+
s = filepath.FromSlash(s)
356+
s2 := filepath.Join("/", s)
357+
if strings.HasSuffix(s, string(filepath.Separator)+".") {
358+
if s2 != string(filepath.Separator) {
359+
s2 += string(filepath.Separator)
360+
}
361+
s2 += "."
362+
} else if strings.HasSuffix(s, string(filepath.Separator)) && s2 != string(filepath.Separator) {
363+
s2 += string(filepath.Separator)
364+
}
365+
return s2, nil
366+
}

0 commit comments

Comments
 (0)