-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Tonis Tiigi <[email protected]>
- Loading branch information
1 parent
b2b0e3d
commit 2be999b
Showing
2 changed files
with
246 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
package file | ||
|
||
import ( | ||
"context" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/containerd/continuity/fs" | ||
"github.com/moby/buildkit/snapshot" | ||
"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes" | ||
"github.com/moby/buildkit/solver/pb" | ||
"github.com/pkg/errors" | ||
copy "github.com/tonistiigi/fsutil/copy" | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir) error { | ||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if action.MakeParents { | ||
if err := os.MkdirAll(p, os.FileMode(action.Mode&0777)); err != nil { | ||
return err | ||
} | ||
} else { | ||
if err := os.Mkdir(p, os.FileMode(action.Mode&0777)); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
if action.Timestamp != -1 { | ||
st := unix.Timespec{Sec: action.Timestamp / 1e9, Nsec: action.Timestamp % 1e9} | ||
timespec := []unix.Timespec{st, st} | ||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, p, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil { | ||
return errors.Wrapf(err, "failed to utime %s", p) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func mkfile(ctx context.Context, d string, action pb.FileActionMkFile) error { | ||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := ioutil.WriteFile(p, action.Data, os.FileMode(action.Mode)|0777); err != nil { | ||
return err | ||
} | ||
|
||
if action.Timestamp != -1 { | ||
st := unix.Timespec{Sec: action.Timestamp / 1e9, Nsec: action.Timestamp % 1e9} | ||
timespec := []unix.Timespec{st, st} | ||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, p, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil { | ||
return errors.Wrapf(err, "failed to utime %s", p) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func rm(ctx context.Context, d string, action pb.FileActionRm) error { | ||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := os.RemoveAll(p); err != nil { | ||
if os.IsNotExist(errors.Cause(err)) && action.AllowNotFound { | ||
return nil | ||
} | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy) error { | ||
// // src is the source path | ||
// Src string `protobuf:"bytes,1,opt,name=src,proto3" json:"src,omitempty"` | ||
// // dest path | ||
// Dest string `protobuf:"bytes,2,opt,name=dest,proto3" json:"dest,omitempty"` | ||
// // optional owner override | ||
// Owner *ChownOpt `protobuf:"bytes,4,opt,name=owner" json:"owner,omitempty"` | ||
// // optional permission bits override | ||
// Mode int32 `protobuf:"varint,5,opt,name=mode,proto3" json:"mode,omitempty"` | ||
// // followSymlink resolves symlinks in src | ||
// FollowSymlink bool `protobuf:"varint,6,opt,name=followSymlink,proto3" json:"followSymlink,omitempty"` | ||
// // dirCopyContents only copies contents if src is a directory | ||
// DirCopyContents bool `protobuf:"varint,7,opt,name=dirCopyContents,proto3" json:"dirCopyContents,omitempty"` | ||
// // attemptUnpackDockerCompatibility detects if src is an archive to unpack it instead | ||
// AttemptUnpackDockerCompatibility bool `protobuf:"varint,8,opt,name=attemptUnpackDockerCompatibility,proto3" json:"attemptUnpackDockerCompatibility,omitempty"` | ||
// // createDestPath creates dest path directories if needed | ||
// CreateDestPath bool `protobuf:"varint,9,opt,name=createDestPath,proto3" json:"createDestPath,omitempty"` | ||
// // allowWildcard allows filepath.Match wildcards in src path | ||
// AllowWildcard bool `protobuf:"varint,10,opt,name=allowWildcard,proto3" json:"allowWildcard,omitempty"` | ||
// // allowEmptyWildcard doesn't fail the whole copy if wildcard doesn't resolve to files | ||
// AllowEmptyWildcard bool `protobuf:"varint,11,opt,name=allowEmptyWildcard,proto3" json:"allowEmptyWildcard,omitempty"` | ||
// // optional created time override | ||
// Timestamp int64 `protobuf:"varint,12,opt,name=timestamp,proto3" json:"timestamp,omitempty"` | ||
|
||
srcp, err := fs.RootPath(src, filepath.Join(filepath.Join("/", action.Src))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
destp, err := fs.RootPath(dest, filepath.Join(filepath.Join("/", action.Dest))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := copy.Copy(ctx, srcp, destp); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type FileBackend struct { | ||
} | ||
|
||
func (fb *FileBackend) Mkdir(ctx context.Context, m fileoptypes.Mount, action pb.FileActionMkDir) error { | ||
mnt, ok := m.(*Mount) | ||
if !ok { | ||
return errors.Errorf("invalid mount type %T", m) | ||
} | ||
|
||
lm := snapshot.LocalMounter(mnt.m) | ||
dir, err := lm.Mount() | ||
if err != nil { | ||
return err | ||
} | ||
defer lm.Unmount() | ||
|
||
return mkdir(ctx, dir, action) | ||
} | ||
|
||
func (fb *FileBackend) Mkfile(ctx context.Context, m fileoptypes.Mount, action pb.FileActionMkFile) error { | ||
mnt, ok := m.(*Mount) | ||
if !ok { | ||
return errors.Errorf("invalid mount type %T", m) | ||
} | ||
|
||
_ = mnt | ||
|
||
return errors.Errorf("mkfile not implemented") | ||
} | ||
func (fb *FileBackend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileActionRm) error { | ||
mnt, ok := m.(*Mount) | ||
if !ok { | ||
return errors.Errorf("invalid mount type %T", m) | ||
} | ||
_ = mnt | ||
|
||
return errors.Errorf("rm not implemented") | ||
} | ||
func (fb *FileBackend) Copy(ctx context.Context, m1 fileoptypes.Mount, m2 fileoptypes.Mount, action pb.FileActionCopy) error { | ||
mnt1, ok := m1.(*Mount) | ||
if !ok { | ||
return errors.Errorf("invalid mount type %T", m1) | ||
} | ||
mnt2, ok := m2.(*Mount) | ||
if !ok { | ||
return errors.Errorf("invalid mount type %T", m2) | ||
} | ||
|
||
_ = mnt1 | ||
_ = mnt2 | ||
return errors.Errorf("copy not implemented") | ||
} | ||
|
||
// type Backend interface { | ||
// Mkdir(context.Context, Mount, pb.FileActionMkDir) error | ||
// Mkfile(context.Context, Mount, pb.FileActionMkFile) error | ||
// Rm(context.Context, Mount, pb.FileActionRm) error | ||
// Copy(context.Context, Mount, Mount, pb.FileActionCopy) error | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package file | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/moby/buildkit/cache" | ||
"github.com/moby/buildkit/snapshot" | ||
"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
type RefManager struct { | ||
cm cache.Manager | ||
} | ||
|
||
func (rm *RefManager) Prepare(ctx context.Context, ref fileoptypes.Ref, readonly bool) (fileoptypes.Mount, error) { | ||
ir, ok := ref.(cache.ImmutableRef) | ||
if !ok { | ||
return nil, errors.Errorf("invalid ref type: %T", ref) | ||
} | ||
|
||
if ir != nil && readonly { | ||
m, err := ir.Mount(ctx, readonly) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Mount{m: m}, nil | ||
} | ||
|
||
mr, err := rm.cm.New(ctx, ir, cache.WithDescription("fileop target")) | ||
if err != nil { | ||
return nil, err | ||
} | ||
m, err := mr.Mount(ctx, readonly) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Mount{m: m, mr: mr}, nil | ||
} | ||
|
||
func (rm *RefManager) Commit(ctx context.Context, mount fileoptypes.Mount) (fileoptypes.Ref, error) { | ||
m, ok := mount.(*Mount) | ||
if !ok { | ||
return nil, errors.Errorf("invalid mount type %T", mount) | ||
} | ||
if err := m.Release(context.TODO()); err != nil { | ||
return nil, err | ||
} | ||
if m.mr == nil { | ||
return nil, errors.Errorf("invalid mount without active ref for commit") | ||
} | ||
return m.mr.Commit(ctx) | ||
} | ||
|
||
type Mount struct { | ||
m snapshot.Mountable | ||
mr cache.MutableRef | ||
} | ||
|
||
func (m *Mount) Release(ctx context.Context) error { | ||
m.m.Release() | ||
if m.mr != nil { | ||
return m.mr.Release(ctx) | ||
} | ||
return nil | ||
} | ||
func (m *Mount) IsFileOpMount() {} |