-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add FileActionSymlink and llb.Symlink
#5519
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,13 @@ func (fa *FileAction) Mkfile(p string, m os.FileMode, dt []byte, opt ...MkfileOp | |
return a | ||
} | ||
|
||
// Symlink creates a symlink at `newpath` that points to `oldpath` | ||
func (fa *FileAction) Symlink(oldpath, newpath string, opt ...SymlinkOption) *FileAction { | ||
a := Symlink(oldpath, newpath, opt...) | ||
a.prev = fa | ||
return a | ||
} | ||
|
||
func (fa *FileAction) Rm(p string, opt ...RmOption) *FileAction { | ||
a := Rm(p, opt...) | ||
a.prev = fa | ||
|
@@ -193,6 +200,7 @@ type ChownOption interface { | |
MkdirOption | ||
MkfileOption | ||
CopyOption | ||
SymlinkOption | ||
} | ||
|
||
type mkdirOptionFunc func(*MkdirInfo) | ||
|
@@ -290,6 +298,10 @@ func (co ChownOpt) SetCopyOption(mi *CopyInfo) { | |
mi.ChownOpt = &co | ||
} | ||
|
||
func (co ChownOpt) SetSymlinkOption(si *SymlinkInfo) { | ||
si.ChownOpt = &co | ||
} | ||
|
||
func (co *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt { | ||
if co == nil { | ||
return nil | ||
|
@@ -337,6 +349,57 @@ func Mkfile(p string, m os.FileMode, dt []byte, opts ...MkfileOption) *FileActio | |
} | ||
} | ||
|
||
// SymlinkInfo is the modifiable options used to create symlinks | ||
type SymlinkInfo struct { | ||
ChownOpt *ChownOpt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the man pages, symlink permissions are irrelevant. Is the mode for the SUID, SGID, and sticky bits? What effect do those have on symlinks? |
||
CreatedTime *time.Time | ||
} | ||
|
||
func (si *SymlinkInfo) SetSymlinkOption(si2 *SymlinkInfo) { | ||
*si2 = *si | ||
} | ||
|
||
type SymlinkOption interface { | ||
SetSymlinkOption(*SymlinkInfo) | ||
} | ||
|
||
// Symlink creates a symlink at `newpath` that points to `oldpath` | ||
func Symlink(oldpath, newpath string, opts ...SymlinkOption) *FileAction { | ||
var si SymlinkInfo | ||
for _, o := range opts { | ||
o.SetSymlinkOption(&si) | ||
} | ||
|
||
return &FileAction{ | ||
action: &fileActionSymlink{ | ||
oldpath: oldpath, | ||
newpath: newpath, | ||
info: si, | ||
}, | ||
} | ||
} | ||
|
||
type fileActionSymlink struct { | ||
oldpath string | ||
newpath string | ||
info SymlinkInfo | ||
} | ||
|
||
func (s *fileActionSymlink) addCaps(f *FileOp) { | ||
addCap(&f.constraints, pb.CapFileSymlinkCreate) | ||
} | ||
|
||
func (s *fileActionSymlink) toProtoAction(_ context.Context, _ string, base pb.InputIndex) (pb.IsFileAction, error) { | ||
return &pb.FileAction_Symlink{ | ||
Symlink: &pb.FileActionSymlink{ | ||
Oldpath: s.oldpath, | ||
Newpath: s.newpath, | ||
Owner: s.info.ChownOpt.marshal(base), | ||
Timestamp: marshalTime(s.info.CreatedTime), | ||
}, | ||
}, nil | ||
} | ||
|
||
type MkfileOption interface { | ||
SetMkfileOption(*MkfileInfo) | ||
} | ||
|
@@ -606,6 +669,10 @@ func (c CreatedTime) SetMkfileOption(mi *MkfileInfo) { | |
mi.CreatedTime = (*time.Time)(&c) | ||
} | ||
|
||
func (c CreatedTime) SetSymlinkOption(si *SymlinkInfo) { | ||
si.CreatedTime = (*time.Time)(&c) | ||
} | ||
|
||
func (c CreatedTime) SetCopyOption(mi *CopyInfo) { | ||
mi.CreatedTime = (*time.Time)(&c) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,6 +178,41 @@ func TestFileMkfile(t *testing.T) { | |
require.Equal(t, int64(-1), mkdir.Timestamp) | ||
} | ||
|
||
func TestFileSymlink(t *testing.T) { | ||
t.Parallel() | ||
|
||
st := Scratch(). | ||
File(Mkfile("/foo", 0700, []byte("data"))). | ||
File(Symlink("foo", "/bar")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have some tests that chain symlink together with other actions. Atm it is unclear what the point of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably the result of copying and pasting from another test. To be clear about your intent, you want to be sure that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. The actions are all linked together so that the input points to either the input of the fileop or the offset of another action that needs to run before it |
||
def, err := st.Marshal(context.TODO()) | ||
|
||
require.NoError(t, err) | ||
|
||
m, arr := parseDef(t, def.Def) | ||
require.Equal(t, 3, len(arr)) | ||
|
||
dgst, idx := last(t, arr) | ||
require.Equal(t, 0, idx) | ||
require.Equal(t, m[dgst], arr[1]) | ||
|
||
f := arr[1].Op.(*pb.Op_File).File | ||
require.Equal(t, 1, len(arr[1].Inputs)) | ||
require.Equal(t, m[arr[1].Inputs[0].Digest], arr[0]) | ||
require.Equal(t, 0, int(arr[1].Inputs[0].Index)) | ||
|
||
require.Equal(t, 1, len(f.Actions)) | ||
|
||
action := f.Actions[0] | ||
require.Equal(t, 0, int(action.Input)) | ||
require.Equal(t, -1, int(action.SecondaryInput)) | ||
require.Equal(t, 0, int(action.Output)) | ||
|
||
symlink := action.Action.(*pb.FileAction_Symlink).Symlink | ||
|
||
require.Equal(t, "foo", symlink.Oldpath) | ||
require.Equal(t, "/bar", symlink.Newpath) | ||
} | ||
|
||
func TestFileRm(t *testing.T) { | ||
t.Parallel() | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does this check that it is a symlink and that it points to the correct location?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted, will fix this by checking
header.Linkname
and verifying its destination.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done